[英]C# abstract method with base class only implementation?
请考虑以下问题:
你有一个类'A'作为许多其他类似类的基类,例如。 一个叫B的班级
A类在它自身中很有用(并且已经在整个地方使用过),因此不是抽象的。
关键在于您现在希望强制执行一个新协议,要求所有继承自A(包括A本身)的类实现方法'func()'。 如果子类忘记实现func(),则应该存在编译器错误。
class A {
A func() { ret new A(...) }
}
class B : A {
A func() { ret new B(...) }
}
class C : A {
// Should give error : no func()
}
问题清楚了吗? 我不能创建A :: func()抽象,因为我希望能够继续使用A作为具体类。 我无法使其成为虚拟,因为这会导致子类回退到超类(而不是给编译器错误)。
接近解决方案的唯一方法是创建一个新的抽象类A *并使所有自定义类型继承自该类,并将A的所有当前用法替换为具有继承自A *的新类“DefaultA”的具体类。 这看起来很乱。 请告诉我还有其他方法可以做到这一点吗?
如果子类型不覆盖特定方法,则根本无法保持A
具体类型并强制编译器错误。
好吧,正如你所说,你可以创建一个继承自A的中间抽象类X,并要求派生类继承自X.X然后使用签名匹配func
声明一个受保护的抽象方法,并覆盖来自A的func
以调用该方法。 这是一个例子:
class A {
public virtual A func() { ... }
}
abstract class X : A {
protected abstract A funcImpl();
public override A func() { return funcImpl(); }
}
class B : X { /* must now implement funcImpl() to avoid compiler error */ }
class C : X { /* must now implement funcImpl() to avoid compiler error */ }
这种方法的主要问题是要求所有派生类现在继承自X而不是A.因此,您只是将执行问题从一种更改为另一种。
在我看来,更ABase
方法是将A
重构为基类ABase
并在那里使用func
。 然后密封A
并要求B
和C
继承ABase
而不是A
:
class ABase {
public abstract ABase func(); }
sealed class A : ABase {
public override ABase func() { ... }
}
class B : ABase {
// forced to override func()
public override ABase func() { ... }
}
你必须用ABase
替换A
所有用途 - 但是在Visual Studio中有一些优秀的重构工具(以及像ReSharper这样的第三方工具),这使得它比以前更加痛苦。
如果这是你需要做的,那么是的。
但在我看来,您可能希望重新考虑这一要求。 我经常实现类似的框架,在子类中强制实现是一个聪明的伎俩。 然后我发现,作为这些框架的使用者 ,我会复制代码或默认为一些无法实现(如空方法)。 这两者都不是理想的,因为它们会增加杂乱和噪音,并降低可维护性。
此外,如果此模式的应用程序是自行工作(即您的示例具有返回其自身实例的子类),那么您可能希望尝试不同的东西,例如正确的工厂模式。 呃,通过“尝试”,我的意思是利用一个控制容器的反转,如Castle Windsor,Ninject,Unity。
如果A类是抽象的,则无法实例化它。 从而,
new A();
和
abstract A func(); // within the A class definition
是矛盾的。
如果你避开抽象,而转向虚拟,你可以得到运行时 (不是编译时)检查:
// In the A class definition.
protected virtual A func()
{
if (GetType() != typeof(A))
throw // ...
}
基本上,你要我们“让这个休息,但不要让这个休息。” 也许你看到了固有的冲突。
这是基类只应用作基类,而不是自己使用的原因之一。
这可能更麻烦,但您可能会强制B,C,D等实现需要func()的接口。 然后确保它们总是通过工厂方法构建。 所以有些模糊:
public class B: A, IFunc{
private B(){}
public static B Create(){ return new B(); }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.