我想用派生类类型覆盖虚方法 . 目前最好的方法是什么?到目前为止,我发现了两种方法:
-
对每个派生类型使用
abstract
baseclass
;用protected
方法桥接 . -
将
protected
实现与public
访问器一起使用 .
基本情况(未实施解决方案, Clone
始终返回基本类型 A1
):
public class A1
{
public int X1 { get; set; }
public A1(int x1) { this.X1 = x1; }
public virtual A1 Clone() { return new A1(X1); }
}
public class A2 : A1
{
public int X2 { get; set; }
public A2(int x1, int x2) : base(x1) { this.X2 = x2; }
public override A1 Clone() { return new A2(X1, X2); } //can't explicitly return A2
}
public class A3 : A2
{
public int X3 { get; set; }
public A3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
public override A1 Clone() { return new A3(X1, X2, X3); } //can't explicitly return A3
}
解决方案#1(对于具有 protected
网桥的每个派生类型使用 abstract
基类):
public class B1
{
public int X1 { get; set; }
public B1(int x1) { this.X1 = x1; }
public virtual B1 Clone() { return new B1(X1); }
}
public abstract class B2_Base : B1
{
public B2_Base(int x1) : base(x1) { }
public sealed override B1 Clone() { return this.CloneAsB1(); }
protected abstract B1 CloneAsB1();
}
public class B2 : B2_Base
{
public int X2 { get; set; }
public B2(int x1, int x2) : base(x1) { this.X2 = x2; }
protected sealed override B1 CloneAsB1() { return this.Clone(); }
public new virtual B2 Clone() { return new B2(X1, X2); } //CAN explicitly return B2
}
public abstract class B3_Base : B2
{
public B3_Base(int x1, int x2) : base(x1, x2) { }
public sealed override B2 Clone() { return this.CloneAsB2(); }
protected abstract B2 CloneAsB2();
}
public class B3 : B3_Base
{
public int X3 { get; set; }
public B3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
protected sealed override B2 CloneAsB2() { return this.Clone(); }
public new virtual B3 Clone() { return new B3(X1, X2, X3); } //CAN explicitly return B3
}
解决方案#2(使用带 public
访问器的 protected
实现):
public class C1
{
public int X1 { get; set; }
public C1(int x1) { this.X1 = x1; }
public C1 Clone() { return this.CloneImplementation(); }
protected virtual C1 CloneImplementation() { return new C1(X1); }
}
public class C2 : C1
{
public int X2 { get; set; }
public C2(int x1, int x2) : base(x1) { this.X2 = x2; }
public new C2 Clone() { return this.CloneImplementation() as C2; } //trusts CloneImplementation to return a C2
protected override C1 CloneImplementation() { return new C2(X1, X2); }
}
public class C3 : C2
{
public int X3 { get; set; }
public C3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
public new C3 Clone() { return this.CloneImplementation() as C3; } //trusts CloneImplementation to return a C3
protected override C1 CloneImplementation() { return new C3(X1, X2, X3); }
}
据我所知,解决方案#1是最严格的方法,但它需要 abstract
base class
为每个派生的 class
想要替换基础 class
的返回类型 .
解决方案#2 's simpler and easier to understand, but it has a small break in internal type safety. Specifically, each derived type' s public
accessor信任其 protected
方法将返回正确的类型 . 所以可以有一个内部类型断开,例如:
public class C2 : C1
{
public int X2 { get; set; }
public C2(int x1, int x2) : base(x1) { this.X2 = x2; }
public new C2 Clone() { return this.CloneImplementation() as C2; } //trusts CloneImplementation to return a C2
protected override C1 CloneImplementation() { return new C1(X1); }
}
是否有一个正确的(普遍接受的)最佳实践来覆盖派生类型的方法?
3 回答
您可以使基类通用:
然而,这让我想知道有一个共同的基类是多么有用 . 也许Derived1和Derived2的Clone实现不需要是通用接口的一部分 .
无论如何,
new
关键字隐含地'overrides'基本功能 . 除非出于某种原因你特别希望override
出现在代码中,否则单个new
修饰符就足够了 . 我还将探索将克隆功能抽象到接口中,它允许您在以后的代码中做出更多假设 .编辑:由此产生的可能行为:
我建议反对所有这些 . 坚持这些事情的标准接口和模式 . 实施System.ICloneable ......
http://msdn.microsoft.com/en-us/library/system.icloneable(v=vs.110).aspx
简单没有?
如果你必须偏离,我会使用安德鲁凯南建议的泛型 . 但是我仍然会实现System.ICloneable,因为它使类更容易与其他框架互操作 .
另外,ICloneable应该使用受保护的构造函数来实现,例如
这样你可以继承A1 ......