[英]How to override method with derived return type in C#?
我想用派生類類型重寫虛擬方法。 目前最好的方法是什么? 到目前為止,我發現了兩種方法:
abstract
基class
; 與protected
方法的橋梁。 public
訪問器一起使用protected
實現。 基本案例(未實現解決方案, 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(將protected
實現與public
訪問器結合使用):
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是最嚴格的方法,但是它需要每個派生class
的abstract
基class
,該派生class
要替換基class
的返回類型。
解決方案2更簡單易懂,但內部類型安全性方面的漏洞很小。 具體來說,每個派生類型的public
訪問器都相信其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); }
}
是否有正確的(通常被接受的)最佳實踐覆蓋具有派生類型的方法?
您可以使基類通用:
public abstract class Base<TDerived> where TDerived : Base {
public abstract TDerived Clone();
}
public class Derived1 : Base<Derived1> {
public override Derived1 Clone() { ... }
}
public class Derived2 : Base<Derived2> {
public override Derived2 Clone() { ... }
}
但是,這使我想知道擁有一個通用基類有多么有用。 也許Derived1和Derived2的Clone實現不需要成為公共接口的一部分。
無論如何, new
關鍵字隱式地“覆蓋”基本功能。 除非出於某種原因,除非您明確希望override
在代碼中出現,否則只有一個new
修飾符就足夠了。 我還將探討將克隆功能抽象到一個接口中,它允許您稍后在代碼中進行更多假設。
public interface ICloneable<out T>
{
T Clone();
}
public class A1 : ICloneable<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, ICloneable<A2>
{
public int X2 { get; set; }
public A2(int x1, int x2)
: base(x1)
{
this.X2 = x2;
}
public virtual new A2 Clone()
{
return new A2(X1, X2);
}
}
public class A3 : A2, ICloneable<A3>
{
public int X3 { get; set; }
public A3(int x1, int x2, int x3)
: base(x1, x2)
{
this.X3 = x3;
}
public virtual new A3 Clone()
{
return new A3(X1, X2, X3);
}
}
編輯:結果可能的行為:
public class A4 : A3, ICloneable<A4>
{
public int X4 { get; set; }
public A4(int x1, int x2, int x3, int x4)
: base(x1, x2, x3)
{
this.X4 = x4;
}
public override A3 Clone()
{
return ((ICloneable<A4>)this).Clone();
}
A4 ICloneable<A4>.Clone()
{
return new A4(X1, X2, X3, X4);
}
}
我不建議所有這些。 只需遵循此類標准接口和模式即可。 實施System.ICloneable ...
http://msdn.microsoft.com/zh-CN/library/system.icloneable(v=vs.110).aspx
Object Clone()
簡單不?
如果您必須偏離,我會按照安德魯·肯南(Andrew Kennan)的建議使用泛型。 但是,我仍將實現System.ICloneable,因為它使該類與其他框架更可互操作。
另外,ICloneable應該使用受保護的構造函數來實現,例如
public class A1 : ICloneable
{
public A1(int x1) { this.X1 = x1; }
protected A1(A1 copy) { this.X1 = copy.X1; }
public int X1 { get; set; }
public virtual object Clone()
{
return new A1(this); // Protected copy constructor
}
}
這樣,您可以像這樣繼承A1 ...
public class B1 : A1, ICloneable
{
public B1(int x1, int y1) : base(x1) { this.Y1 = y1; }
protected B1(B1 copy) : base(copy) { this.Y1 = copy.Y1; }
public int Y1 { get; set; }
public virtual object Clone()
{
return new B1(this); // Protected copy constructor
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.