C#:用于启用实现和重写的接口和抽象

C#:用于启用实现和重写的接口和抽象,c#,interface,overriding,implementation,abstract,C#,Interface,Overriding,Implementation,Abstract,我要设计5个不同的班级 这些课程的很多部分都非常相似,但它们有一些细微的差别(当然) 如果我编写了一个由我设计的每个类实现的接口,那么必须完整地编写接口中的每个抽象方法 如果我编写了一个base类,而我设计的每个类都是从该类派生的,那么每个类都会在我在base类中创建的virtual方法中自动拥有一些功能,但它们都需要被重写,调用base功能,包括细微的差别 有没有办法结合这些功能?我喜欢要求实现接口的方法,但我也喜欢设置由基本类预先编程的特性 我在这里和其他地方看过很多例子,但看起来没有人像我

我要设计5个不同的班级

这些课程的很多部分都非常相似,但它们有一些细微的差别(当然)

如果我编写了一个由我设计的每个类实现的
接口
,那么必须完整地编写
接口
中的每个
抽象
方法

如果我编写了一个
base
类,而我设计的每个类都是从该类派生的,那么每个类都会在我在
base
类中创建的
virtual
方法中自动拥有一些功能,但它们都需要被重写,调用
base
功能,包括细微的差别

有没有办法结合这些功能?我喜欢要求实现
接口
的方法,但我也喜欢设置由
基本
类预先编程的特性

我在这里和其他地方看过很多例子,但看起来没有人像我所描述的那样。有可能吗

编辑:因此,鉴于此:

abstract class Base
{
    virtual protected void OptionallyOverridable() {}
    abstract protected void SubclassMustImplement();
}
…有没有一种方法可以写出这样的东西:

abstract class Base2
{
    DataEventType EventType;
    DataChangedEventHandler OnDataChange;

    virtual protected void OptionallyOverridable() {}
    abstract protected void SubclassMustImplement() {
      // values here are guaranteed
    }
}

“abstract”关键字就是您要查找的内容

    abstract class Base
    {
        virtual protected void SubclassCanCallAndOptionallyOverride() {}
        abstract protected void SubclassMustBeImplement();
    }
有关更多详细信息:

C#允许类同时继承基类和实现接口,那么为什么不同时执行这两个操作呢

public interface IFoo
{
    public void Bar();
    public bool Baz();
}

public abstract class BaseFoo : IFoo
{
    //fields/properties used in all classes
    public void Bar()
    { //Implementation }

    public bool Baz()
    { //Implementation }
}

public class DerivedFoo : BaseFoo, IFoo {...}

是的,你已经自己回答了。您将同时执行以下两项操作:

  • 有一个基本实现的基类
  • 让子类(或者基类,为什么不呢?)实现您想要的接口

    • AllenG得到了我的加号,但因为我已经把它打出来了,这里是一个更长、更明确的概念演示

      定义你的界面

      public interface IFoo
      {
          void DoIt();
          void DoItWithoutDefaultBehavior();
      }
      
      定义一个基类,该基类使用某些默认行为实现接口,或者某些方法没有默认行为

      public abstract class BaseFoo : IFoo
      {
          public virtual void DoIt()
          {
               // Base behavior
               Console.WriteLine("base");
          }
      
          // This one has no base behavior
          public abstract void DoItWithoutDefaultBehavior();
      }
      
      您的一些子类可能会使用这些默认行为

      public class DerivedFoo1 : BaseFoo, IFoo
      {
          // Doesn't override DoIt, takes BaseFoo
      
          public override void DoItWithoutDefaultBehavior()
          {
              Console.WriteLine("foo1");
          }
      }
      
      其他人可能会加入其中

      public class DerivedFoo2 : BaseFoo, IFoo
      {
          public override void DoIt()
          {
              base.DoIt();
              // Additional stuff
              Console.WriteLine("derived");
          }
      
          public override void DoItWithoutDefaultBehavior()
          {
              Console.WriteLine("foo2");
          }
      }
      
      您可以通过类或接口调用这些方法

      void Main()
      {
          var foo1 = new DerivedFoo1();
          foo1.DoIt();
      
          var foo2 = new DerivedFoo2();
          foo2.DoIt();
      
          IFoo foo1AsFoo = new DerivedFoo1();
          foo1AsFoo.DoIt();
      
          IFoo foo2AsFoo = new DerivedFoo2();
          foo2AsFoo.DoIt();
      }
      
      另请参阅:其中讨论了
      DerivedFoo1
      DerivedFoo2
      是否应重申,当
      BaseFoo
      已经这样说时,它们应实现
      IFoo
      。在我的例子中,他们这样做是为了明确

      编辑 向界面添加事件是绝对可能的。我对我的示例做了以下更改。您可以进行类似的更改:

      • 接口IFoo
        中,添加
        事件处理程序event
      • BaseFoo
        中,添加
        公共事件处理程序事件
      • BaseFoo.DoIt
        中,添加
        if(TheEvent!=null)
        {
        var args=新事件args();
        事件(本,args);
        }
      • 添加
        public void处理程序(对象发送方,事件参数e)
        {
        控制台。WriteLine(“已发射”);
        }
      • Main
        中,添加
        foo1.TheEvent+=TheHandler
      输出现在变为

      base
      Fired.
      base
      derived
      base
      base
      derived
      

      你可以混合界面和抽象,我想你想要的是这样的东西

      public interface IFoo
      {
          void ImplementMe();
          int ImplementId { get; }
      }
      
      public abstract class BaseFoo : IFoo
      {
          public virtual void ImplementMe()
          {
              CommonStuff();
          }
      
          public abstract int ImplementId { get; }
      
          private void CommonStuff()
          {
              // ... do stuff ?
          }
      }
      
      public sealed class FooImplementationA : BaseFoo
      {
          public override int ImplementId { get { return 0; } }
      
          public override void ImplementMe()
          {
              MoreStuff();
              base.CommonStuff();
          }
      
          private void MoreStuff()
          {
              // ... do more stuff.
          }
      }
      
      public sealed class FooImplementationB : BaseFoo
      {
          public override int ImplementId { get { return 1; } }
      
          public override void ImplementMe()
          {
              DifferentStuff();
              base.CommonStuff();
          }
      
          private void DifferentStuff()
          {
              // ... do different stuff.
          }
      }
      

      但是,你也不需要这个接口,只需使用
      BaseFoo
      抽象类就可以了。不清楚你在编辑中要求的是什么。要使所有这些类似的类表现相同,它们都需要实现某些功能(即我的自定义事件)。只需将这些事件放在您的界面上。
      界面
      可以处理我所需要的大部分内容,但我确实希望实现该
      界面
      的类中有一些保证的自定义类型和值。这能做到吗?我想这就是我一直在寻找的答案。我想我可能必须在基类中实现接口,并以某种方式将其应用到派生类中。我需要离开显示器,思考几分钟。它看起来不像我想要的那样。仅供参考:我也看到了AllenG的版本,但不知道该去哪里。感谢您的详细解释。有没有办法将事件添加到您的界面?我已经试过了,但由于某些原因,这些事件在我的派生类中不可访问或可见。我肯定我做错了什么。