.net不允许在基类中实现部分接口。作为缓解措施,我已经提出了3种替代解决方案。请帮我决定哪些在重构,编译/运行时错误,可读性方面更具普遍性。 但首先是几条评论。
我的比较:
public interface IFoo
{
void Method1();
void Method2();
}
public abstract class BaseClass1 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
void IFoo.Method2()
{
IFooMethod2();
}
protected abstract void IFooMethod2();
}
public class MyClass1 : BaseClass1
{
[Obsolete("Prohibited direct call from child classes. only inteface implementation")]
protected override void IFooMethod2()
{
//some implementation
}
}
public abstract class BaseClass2 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
[Obsolete("Prohibited direct call from child classes. only inteface implementation")]
public virtual void Method2()
{
throw new NotSupportedException();
}
}
public abstract class MyClass2 : BaseClass2
{
public override void Method2()
{
//some implementation
}
}
public abstract class BaseClass3 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
void IFoo.Method2()
{
throw new NotSupportedException();
}
}
public abstract class MyClass3 : BaseClass3, IFoo
{
void IFoo.Method2()
{
//some implementation
}
}
答案 0 :(得分:9)
我喜欢这个版本,基类不能实例化,因为它的抽象,派生类必须在其声明中列出IFoo,否则它将不会实现接口,然后它全部负责实现其余的界面。 我可以看到的一个缺点是你不能在基类中显式实现接口方法(即没有IFoo:Method1),否则这是一个相当低的开销版本。
public interface IFoo
{
void Method1();
void Method2();
}
public abstract class BaseClass1
{
public void Method1()
{
//some implementation
}
}
public class MyClass1 : BaseClass1, IFoo
{
public void Method2()
{
//some implementation
}
}
答案 1 :(得分:6)
设计一个没有实现明确定义的合同的类是非常糟糕的。这是极端的,因为你首先说一个班级能够做某事。你明确地强调了类可以做的东西,但是后来在代码中你说nahh,搞砸了,这个类可以在没有实现的情况下生存。编译器非常明智地要求您实施合同,但由您决定。
以下是一些常见的解决方案
糟糕的解决方案
更好的解决方案
最佳解决方案
答案 2 :(得分:5)
好的,您可以尝试以下操作,因为BaseClass
是抽象的:
public interface IFoo
{
void Method1();
void Method2();
}
public abstract class BaseClass : IFoo
{
public void Method1()
{
// Common stuff for all BaseClassX classes
}
// Abstract method: it ensures IFoo is fully implemented
// by all classes that inherit from BaseClass, but doesn't provide
// any implementation right here.
public abstract void Method2();
}
public class MyClass1 : BaseClass
{
public override void Method2()
{
// Specific stuff for MyClass1
Console.WriteLine("Class1");
}
}
public class MyClass2 : BaseClass
{
public override void Method2()
{
// Specific stuff for MyClass2
Console.WriteLine("Class2");
}
}
private static void Main(string[] args)
{
IFoo test1 = new MyClass1();
IFoo test2 = new MyClass2();
test1.Method2();
test2.Method2();
Console.ReadKey();
}
答案 3 :(得分:0)
我建议让抽象基类使用调用protected abstract
方法的方法实现接口,如第一个示例所示,除了某些派生类可能无法实现的方法(在“将所有内容输入之后) IList
但是没有所有方法实际上工作“模式”;那些可能是protected virtual
存根,它们会抛出NotSupportedException
。
请注意,是否要将接口的任何特定成员公开为类似命名的公共成员(可以调用相应的抽象成员),这取决于子类。
VB.net中的正确模式类似于MustOverride Sub IFoo_Method1() Implements IFoo.Method1
,这将避免额外的函数调用开销,但C#不提供任何实现与受保护成员的接口的方法。对于可能必须在子类中重写的任何方法使用显式接口实现有点icky,因为孩子重新实现接口不可能链接到父实现。