我在今天之前从未遇到过这个问题,并且想知道实现这种行为的惯例/最佳实践是什么。
基本设置是:
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模型的代码生成,强制所有类设计必须首先从模型完成。代码生成工具是导致接口方法被明确实现的原因(不想辩论它的优点和缺点,这正是我现在不得不处理的,因此隐式实现不是一个选项)
答案 0 :(得分:14)
或者,您可以采用以下两种方式之一:
首先,不要明确地实现接口:
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();
}
}
答案 1 :(得分:11)
是的,您可以明确重新声明您要实施IDispatch
,并在Bar
中再次明确实施。
但,您将无法在Foo
中调用原始实现。如果您需要这样做,您需要更改Foo
以使用隐式接口实现和虚拟方法(可以覆盖,然后在base.Dispatch()
中使用Bar
调用)或使Foo
实现调用成为受保护的虚拟方法,再次在Bar
覆盖。
答案 2 :(得分:3)
Bar已经实现了IDispatch,如果它是Foo的子类,则无需明确说明。如果你想以不同的方式只实现一种接口方法,那就这样做:
IDispatch { void Method(); }
Foo : IDispatch { public virtual void Method() { implementation1 } }
Bar : Foo { public override void Method() { implementation2 } }
答案 3 :(得分:2)
您不必执行IDispatch.Dispatch
- 只要您的班级中有一个名为Dispatch
的方法,您就会实现该界面。
你可以这样做,它为我构建:
public class Foo : IDispatch
{
public virtual void Dispatch()
{
}
}
public class Bar : Foo
{
public override void Dispatch()
{
base.Dispatch();
}
}
答案 4 :(得分: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