17

我在今天之前从未遇到过这个问题,并且想知道完成这种行为的约定/最佳实践是什么。

基本设置是这样的:

public interface IDispatch {
    void Dispatch();
}

public class Foo : IDispatch {
    void IDispatch.Dispatch() {
        DoSomething();
    }
}

public class Bar : Foo {
     ...
}

Bar 需要继承 Foo 的子类,因为它与 Bar 共享所有相同的属性,并且引入了我需要遇到的 2 个新属性。我遇到的问题是 Foo 还需要稍微不同的 Dispatch() 实现。通常它会被覆盖,但这对于接口方法无效,所以让 Bar 实现 IDispatch 也可以,所以我的类定义如下所示:

public class Bar : Foo, IDispatch { .... }

然后在 Bar 中也对该接口方法进行显式实现?当我尝试这样做时,我的编译器似乎没有抱怨,但我不确定它是否会导致任何运行时问题解决在路上使用哪个实现,或者是否有更好的方法来完成这样的事情。

另外值得一提的是,在我的工作场所,我们使用 UML 模型生成代码,这强制所有类设计必须首先从模型完成。代码生成工具是导致显式实现接口方法的原因(不想争论这个的利弊,这正是我现在被迫处理的,所以不能选择隐式实现)

4

5 回答 5

18

或者,您可以通过以下两种方式之一执行此操作:

首先,不要显式实现接口:

public class Foo : IDispatch {
    public virtual void Dispatch() {
        whatever();
    }
}

public class Bar : Foo {
    public override void Dispatch() {
        whateverElse();
    }
}

其次,显式实现它,但添加一个子类可以覆盖的函数:

public class Foo : IDispatch {
    void IDispatch.Dispatch() {
        this.Dispatch();
    }

    protected virtual void Dispatch() {
        whatever();
    }
}

public class Bar : Foo {
    protected override void Dispatch() {
        whateverElse();
    }
}
于 2012-11-22T16:00:04.110 回答
13

是的,你可以明确地重新声明你想要实现IDispatch,然后在Bar.

但是,您将无法在Foo. 如果您需要这样做,您需要更改Foo为使用带有虚拟方法的隐式接口实现(可以覆盖然后用base.Dispatch()in调用Bar),或者使Foo实现调用一个受保护的虚拟方法,您将再次覆盖 in Bar.

于 2012-11-22T15:59:15.050 回答
4

如果 Bar 是 Foo 的子类,它已经实现了 IDispatch,无需明确说明。如果您只想以不同的方式实现一种接口方法,请执行以下操作:

IDispatch { void Method(); }
Foo : IDispatch { public virtual void Method() { implementation1 } }
Bar : Foo { public override void Method() { implementation2 } }
于 2012-11-22T16:01:17.050 回答
2

您不必这样做IDispatch.Dispatch- 只要Dispatch在您的类中调用了一个方法,您就已经实现了该接口。

你可以这样做,它为我构建:

  public class Foo : IDispatch
  {
    public virtual void Dispatch()
    {
    }
  }
  public class Bar : Foo
  {
    public override void Dispatch()
    {
      base.Dispatch();
    }
  }
于 2012-11-22T16:00:27.843 回答
0

我更喜欢显式实现接口。不熟悉您的代码库的人更容易理解什么是接口与特定于类的逻辑。

您仍然可以在显式实现接口的同时完成类继承。您只需要让基类实现接口,并将该实现调用到可以扩展的虚函数中。这是一个例子:

interface Inter
{
    void Call();
}

class A : Inter
{
    //Explicitly implemented interface
    void Inter.Call()
    {
        this.Call();
    }

    public virtual void Call() { Console.WriteLine("Base call in A"); }
}

class B : A
{
    public override void Call()
    {
        Console.WriteLine( "Called B" );
    }
}

class Program
{
    static void Main( string[] args )
    {
        var a = new A();   //Base class
        var aa = (Inter)a; //Interface only
        a.Call();
        aa.Call();

        var b = new B();   //Child class
        var bb = (Inter)b; //Interface only of Child class
        b.Call();
        bb.Call();

        //See the output before the console program closes
        Console.ReadLine();         
    }
}

程序输出:

Base call in A
Base call in A
Called B
Called B
于 2019-10-17T16:54:42.473 回答