C#接口和基类

C#接口和基类,c#,oop,inheritance,C#,Oop,Inheritance,我有一个C#接口和一个实现该接口的具体类。现在我想创建另一个实现该接口的类。很简单 然而,大多数方法在类中都是完全相同的,只有几个方法会真正改变 我不想复制我的第二个类中包含的第一个类中的所有逻辑 我如何创建第二个类,并在第一个类中使用逻辑,除了额外的东西 我的接口称为IEventRepository,我的第一个类称为BaseEvents。现在我想创建一个名为FooBarEvents的新类 我对FooBarEvents的类定义是: public class FooBarEvents : Base

我有一个C#接口和一个实现该接口的具体类。现在我想创建另一个实现该接口的类。很简单

然而,大多数方法在类中都是完全相同的,只有几个方法会真正改变

我不想复制我的第二个类中包含的第一个类中的所有逻辑

我如何创建第二个类,并在第一个类中使用逻辑,除了额外的东西

我的接口称为IEventRepository,我的第一个类称为BaseEvents。现在我想创建一个名为FooBarEvents的新类

我对FooBarEvents的类定义是:

public class FooBarEvents : BaseEvents, IEventRepository
我的意图是在复制代码的每个方法中使用return base.Method()


我假设这是不正确的?

因为
BaseEvents
已经实现了
IEventRepository
,您不需要在
FooBarEvents
中再次实现它
FooBarEvents
自动继承
BaseEvents
'实现。

您可以让第二个类扩展第一个类。您的第一个类可以是抽象的,但只能实现接口中的常用方法。

fooberavents
应该只需要从
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)
{ ... }

如果
IEventRepository
BaseEvents
实现中的某个方法选择总是要维护相同的实现,那么您可以在
BaseEvents
类中实现它们,并将可能更改为
virtual
的方法标记出来。这样,如果
FooBarEvents
希望更改其中一个方法的实现,它可以简单地覆盖它


关于将
IEventsRepository
添加到
FooBarEvents
类,请注意:这样做是有效的。有关Jon Skeet的答案,请参阅。

为什么不将基类中的方法定义为
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() {...}
}
baronstroids
将继承
Bar
的所有行为,您可以通过在
baronstroids
中重写它们来更改所需任何方法的特定行为(它们需要在基类
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
接口的方法的特定行为。如果您只想将附加功能添加到
baronstroids
,那么只需继承表单
Bar
即可继承其所有功能,并添加所有必需的新方法来实现新功能。

以下代码显示了如何使用抽象基类提供某些接口方法的通用实现,并为其他人提供自定义实现

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
    }
  }
公共接口IEventRepository
{
void方法1();
void方法2();
}
公共抽象类BaseEvents:IEventRepository
{
公共无效方法1()
{
Console.WriteLine(“这是共享功能”);
}
公开摘要无效方法2();
}
公共类实现1:BaseEvents
{
重写公共无效方法2()
{
Console.WriteLine(“Impl1.Method2”);
}
}
公共类实现2:BaseEvents
{
重写公共无效方法2()
{
Console.WriteLine(“Impl2.Method2”);
}
}
公共课程
{
静态void Main(字符串[]参数)
{
var implementations=new List{new Implementation1(),new Implementation2()};
foreach(实现中的var i)
{
WriteLine(i.GetType().Name);
控制台。写入(“\t”);
i、 Method1();//写入“这是共享功能”
控制台。写入(“\t”);
i、 Method2();//写入特定于类型的消息
}
}

}有几种不同的方法

一个。完全跳过接口,使其成为一个抽象类。这在工作时更简单,但您只能有一个基类这一事实限制了在C中的使用#

可以让一个类实现接口,另一个类从接口派生:

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
的定义更加合理,上述内容也可能会导致混淆。

确切地说,您为什么要使用接口?“您可以让您的第二个类扩展您的第二个类”-您的意思是“扩展您的第一个类”?我使用的是Ninject依赖项注入,它不想了解抽象类。您可以在容器中注册实现类-在下面的示例中是Implementation1和Implementation2。抽象类无法实例化,因此它们不能与容器一起工作。因此,如果我使用Bar使用IFoo并调用SpecificBehaviorMethod1,我想我会得到一个NotImplementedException,似乎Baronstroids做了Bar不做的事情?@Pual。请参见编辑以获取答案。简而言之,不行,
Bar
baronstroids
都必须实现
SpecificBehaviorMethod1
,因为此方法是
IFoo
合同的一部分。如果
SpecificBehaviorMethod
是虚拟的,它将调用特定于您正在调用的实例的实际类型的实现。我明白了,但是FooBarEvents类将是特定于客户端的,并且可能还有10个未实现的方法
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