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

本文关键字:重写 接口 抽象 实现 用于 启用 | 更新日期: 2023-09-27 17:56:53

我必须设计大约5个不同的类。

这些类的许多部分将非常相似,但它们会略有不同(当然)。

如果我编写了我设计的每个类实现的interface,则必须完全编写interface中的每个abstract方法。

如果我编写一个 base 类,每个设计类都派生自该类,则每个类将自动在我在 base 类中创建的 virtual 方法中具有一些功能,但它们都需要被重写,调用base功能,以包含细微的差异。

有没有办法组合这些功能?我喜欢要求实现interface的方法,但我也喜欢设置由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
    }
}

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

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();
}

另见:Eric Lippert的帖子,该帖子讨论了DerivedFoo1DerivedFoo2是否应该重申他们在BaseFoo已经说过的情况下实现了IFoo。在我的示例中,为了明确起见,他们这样做了。

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

  • interface IFoo,请添加event EventHandler TheEvent;
  • BaseFoo,请添加public event EventHandler TheEvent;
  • BaseFoo.DoIt,请添加if (TheEvent != null) { var args = new EventArgs(); TheEvent(this, args); }
  • 添加public void TheHandler(object sender, EventArgs e) { Console.WriteLine("Fired."); }
  • 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抽象类。

"abstract"关键字就是您要查找的内容。

    abstract class Base
    {
        virtual protected void SubclassCanCallAndOptionallyOverride() {}
        abstract protected void SubclassMustBeImplement();
    }

有关更多详细信息:http://msdn.microsoft.com/en-us/library/ms173150.aspx