C#接口和基类
本文关键字:基类 接口 | 更新日期: 2023-09-27 18:20:35
我有一个C#接口,以及一个实现该接口的具体类。我现在想创建另一个实现该接口的类。很简单。
然而,类中的大多数方法都是完全相同的,只有少数方法会发生实际更改。
我不想重复我的第二类中包含在第一类中的所有逻辑。
我如何创建第二个类,并使用第一个类中的逻辑,除了额外的东西?
我的接口叫做IEventRepository,我的第一个类叫做BaseEvents。我现在想创建一个名为FooBarEvents的新类。
我对FooBarEvents的类定义是:
public class FooBarEvents : BaseEvents, IEventRepository
我的意图是使用返回基地。方法()。
我想这是不对的?
FooBarEvents
应该只需要从BaseEvents
继承,而不需要实现IEventRepository
,因为BaseEvents
已经实现了接口。如果需要更改FooBarEvents
中某些IEventRepository
方法的行为,只需覆盖这些方法即可。
编辑:的一些例子
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
自动继承BaseEvents
的实现。
下面的代码展示了如何用抽象基类提供一些接口方法的通用实现,并为其他接口方法提供自定义实现。
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
}
}
}
为什么不将基类中的方法定义为Virtual
,并覆盖要在子类中更改的方法?
您可以使第二个类扩展第一个类。第一个类可以是抽象的,但只能实现接口中的通用方法。
使用继承:
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
中标记为virtual)。
这样你就会有以下内容:
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
即可继承其所有功能,并添加实现新功能所需的所有新方法。
有几种不同的方法。
一个。完全跳过接口,使其成为一个抽象类。当它工作时,这会更简单,但事实上,你只能有一个基类限制了在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
的定义更合理,上述内容也可能导致混淆。
如果IEventRepository
的BaseEvents
实现中的某些方法选择总是保持相同的实现,那么您可以在BaseEvents
类中实现它们,并将可能更改的方法标记为virtual
。这样,如果FooBarEvents
希望更改其中一个方法的实现,它可以简单地覆盖它
关于将IEventsRepository
添加到FooBarEvents
类,请注意:这样做是有效的。请参阅此处获取Jon Skeet对此的回答。