Интерфейс C# и базовые классы
У меня есть C интерфейс#, и конкретный класс, который реализует этот интерфейс. Теперь я хочу создать другой класс, который реализует этот интерфейс. Все очень просто.
однако большинство методов будут точно такими же в классах, и только несколько методов фактически изменятся.
Я не хочу дублировать всю логику в моем 2-м классе, которая содержится в моем первом.
Как создать 2-й класс и использовать логику в моем первом классе, кроме за лишние вещи?
мой интерфейс называется IEventRepository, а мой 1-й класс называется BaseEvents. Теперь я хочу создать новый класс под названием FooBarEvents.
мое определение класса для FooBarEvents:
public class FooBarEvents : BaseEvents, IEventRepository
мое намерение состояло в том, чтобы затем использовать базу возврата.Метод () в каждом методе, который дублирует код.
Я предполагаю, что это не правильно?
8 ответов
FooBarEvents
нужно только наследовать от BaseEvents
, также не реализовать IEventRepository
, as BaseEvents
уже реализует интерфейс. Если вам нужно изменить поведение некоторых IEventRepository
методы FooBarEvents
, просто переопределить эти методы.
Edit: некоторые примеры
interface IEventRepository
{
void CommonMethodA();
void CommonMethodB();
void ImplentationSpecificMethod();
}
abstract class BaseEvents : IEventRepository
{
public void CommonMethodA()
{ ... }
public virtual void CommonMethodB()
{ ... }
public abstract void ImplementationSpecificMethod();
public void BaseEventsMethod()
{ ... }
public void BaseEventsMethod2()
{ ... }
}
class FooBarEvents : BaseEvents
{
public override void CommonMethodB()
{
// now FooBarEvents has a different implementation of this method than BaseEvents
}
public override void ImplementationSpecificMethod()
{
// this must be implemented
}
public new void BaseEventsMethod2()
{
// this hides the implementation that BaseEvents uses
}
public void FooBarEventsMethod()
{
// no overriding necessary
}
}
// all valid calls, assuming myFooBarEvents is instantiated correctly
myFooBarEvents.CommonMethodA()
myFooBarEvents.CommonMethodB()
myFooBarEvents.BaseEventsMethod();
myFooBarEvents.BaseEventsMethod2();
myFooBarEvents.FooBarEventsMethod();
myFooBarEvents.ImplementationSpecificMethod();
// use the contract thusly:
void DoSomethingWithAnEventRepository(BaseEvents events)
{ ... }
С BaseEvents
уже реализует IEventRepository
, вам не нужно реализовывать его снова в FooBarEvents
. FooBarEvents
автоматически наследует '.
почему бы вам не задать ваши методы в базовом классе как Virtual
и переопределить те, которые вы хотите изменить в классе ребенка?
в следующем коде показано, как обеспечить общую реализацию некоторых методов интерфейса с абстрактным базовым классом и предоставить пользовательские реализации для других.
public interface IEventRepository
{
void Method1();
void Method2();
}
public abstract class BaseEvents : IEventRepository
{
public void Method1()
{
Console.WriteLine("This is shared functionality");
}
public abstract void Method2();
}
public class Implementation1 : BaseEvents
{
override public void Method2()
{
Console.WriteLine("Impl1.Method2");
}
}
public class Implementation2 : BaseEvents
{
override public void Method2()
{
Console.WriteLine("Impl2.Method2");
}
}
public class Program
{
static void Main(string[] args)
{
var implementations = new List<IEventRepository> { new Implementation1(), new Implementation2() };
foreach (var i in implementations)
{
Console.WriteLine(i.GetType().Name);
Console.Write("\t");
i.Method1(); // writes 'This is shared functionality'
Console.Write("\t");
i.Method2(); // writes type specific message
}
}
}
вы можете сделать свой второй класс расширить свой первый класс. Ваш первый класс может быть абстрактным, но реализовывать только общие методы из интерфейса.
использовать наследование:
public interface IFoo
{
void GeneralBehaviorMethod1();
void GeneralBehaviorMethod2();
void SpecificBehaviorMethod1();
}
public class Bar: IFoo
{
public void GeneralBehaviorMethod1() {...}
public void GeneralBehaviorMethod2() {...}
public virtual void SpecificBehaviorMethod1() {...}
...
}
public class BarOnSteroids: Bar
{
public override void SpecificBehaviorMethod1() {...}
}
BarOnSteroids
наследует все поведение Bar
и вы можете изменить конкретное поведение любых методов, которые вам нужны, переопределив их в BarOnSteroids
(они должны быть помечены как виртуальные в базовом классе Bar
).
таким образом, у вас будет следующее:
IFoo iFoo = new Bar();
iFoo.SpecificBehaviorMethod1(); //Bar implementation will be called;
IFoo iFoo = new BarOnSteroids();
iFoo.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
iFoo.CommonBehaviorMethod1(); //Bar implementation will be called.
Bar bar = new BarOnSteroids();
bar.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
bar.CommonBehaviorMethod1(); //Bar implementation will be called.
это предполагает, что вы хотите изменить поведение методов, которые являются частью IFoo
интерфейс. Если все, что вы хотите, это добавить дополнительные функции к BarOnSteroids
тогда просто наследовать форму Bar
наследовать все это функциональность и добавить все необходимые новые методы для реализации новой функциональности.
если определенный выбор методов BaseEvents
реализация IEventRepository
are всегда собирается поддерживать ту же реализацию, то вы можете просто реализовать их в BaseEvents
класс и отметьте те, которые может изменить как virtual
. Таким образом, если FooBarEvents
желает изменить реализацию одного из методов, его можно просто переопределить его.
просто Примечание относительно добавления IEventsRepository
на FooBarEvents
class: это действительно сделать. Видеть здесь для ответа Джона Скита об этом.
есть несколько разных подходов.
один. Полностью пропустите интерфейс и сделайте его абстрактным классом. Это проще, когда он работает, но то, что вы можете иметь только один базовый класс ограничивает использование в C#
public abstract class EventRepository
{
public abstract int MustBeOverridden(string str);//classes have to override this
public virtual int CanBeOverridden(int i)//classes can override but may choose not to.
{
return 4;
}
public int CannotOverride(string str)//this is always the same
{
return MustBeOverridden(str) + 3;//can make use of this
}
}
вы можете иметь один класс, реализующий интерфейс, и другой производный от него:
public interface IEventRepository
{
int Method1(string str);
int Method2(string str);
}
public class EventClass1 : IEventRepository
{
public int Method1(string str)//can't be overridden as not marked virtual
{
return 1;
}
public virtual int Method2(string str)//can be overridden
{
return 2;
}
}
public class EventClass2 : EventClass1
{
public override int Method2(string str)
{
return -2;
}
}
пусть они оба переопределяют абстрактный класс, который дает некоторое общее поведение:
public abstract class EventClass : IEventRepository
{
public abstract int Method1(string str);
public int Method2(string str)
{
return 2;
}
}
public class EventClass1 : EventClass
{
public override int Method1(string str)
{
return 1;
}
}
public class EventClass2 : EventClass
{
public override int Method1(string str)
{
return -1;
}
}
они также могут использовать статический помощник класс, который не имеет ничего общего с иерархией, но который предоставляет методы, полезные при реализации функциональности.
будьте осторожны, хотя этот шаблон:
public class EventClass1 : IEventRepository
{
public int Method1(string str)//not override-able
{
return 1;
}
public int Method2(string str)//not override-able
{
return 2;
}
}
public class EventClass2 : EventClass1, IEventRepository
{
//We really want our own Method1!
public new int Method1(string str)
{
return 3;
}
int IEventRepository.Method1(string str)
{
return -1;
}
}
EventClass2 e2 = new EventClass2();
EventClass1 e1 = e2;
IEventRepository ie = e2;
Console.WriteLine(e2.Method1(null));//3
Console.WriteLine(e1.Method1(null));//1
Console.WriteLine(ie.Method1(null));//-1
, даже если IEventRepository.Method1
определяется более разумно, выше, вероятно, приведет к путанице.