2016-09-24 64 views
0

比方說,我有返回B類的一個實例C#:重寫屬性,並返回一個派生類型

public class A 
{ 
    public virtual B Details {get; set;} 
} 

讓我們也說了財產「詳細信息」 A類,我有一個類AEXT (A擴展),從A. 繼承,但我想那Aext.Details返回類Bext(B擴展)的一個實例:

public class Aext : A 
{ 
    public override Bext Details {get; set;} 
} 

這不能編譯,因爲類型Bext必須從繼承的類型相匹配。
當然,我可以很容易地解決這個問題,只需把B作爲Aext的Details的返回。

public class Aext 
{ 
    B Details {get; set;} 
} 

分配工作,但我得查,每次我用AEXT的實例,如果細節Bext或B.

你看到做一些清潔劑,這種解決方案的一種方式?

謝謝。

+0

B是抽象類嗎? – Monah

+0

@Hadi Hassan:不,B不是抽象類。 – zizou

+1

我不認爲我理解你似乎在追求什麼設計,但是你面臨的問題是因爲C#不支持(非接口)虛擬方法中的協變返回類型。因此,您可以聲明一個帶有'Details'返回值的通用接口作爲其泛型類型參數,將其標記爲協變,並且能夠使用它併爲其分配,而不必知道確切的返回類型。 –

回答

2

也許你可以嘗試仿製藥,是這樣的:

public class A<T> where T : B 
{ 
    public T Details { get; set; } 
} 

public class Aext : A<Bext> 
{ 
} 

public class B 
{ 

} 

public class Bext : B 
{ 

} 

如果需要,你可以覆蓋牛逼細節與Bext細節,它會正常工作。

+0

這就是我認爲的最簡潔的方法。 – zizou

0

不是 - 但我認爲它表示基準類的設計存在缺陷。您正嘗試將接口行爲強制到Abstract類/方法上。基本方法什麼都不做,做什麼被繼承?基類可以有每個繼承者訪問的類型B的受保護成員,並通過他們自己的強類型訪問器方法公開。該值可供所有繼承者使用,但消費者需要獲取/設置數據的強類型版本。

0

如果你不希望引入的接口,你可以做這樣的事情:

public class B 
{ } 

public class Bext : B 
{ } 

public class A 
{ 
    public virtual B Details { get; set; } 

    public A() 
    { 
     Details = new B(); 
    } 

} 

public class Aext : A 
{ 
    public override B Details => new Bext(); 
} 

不過,我建議你去的構圖方式,使用依賴注入,像這樣:

public interface IB 
{ } 
public class B : IB 
{ } 

public class Bext : IB 
{ } 

public class A 
{ 
    public virtual IB Details { get; set; } 

    public A(IB details) 
    { 
     Details = details; 
    } 
} 

public class TestClass 
{ 
    public void TestMethod() 
    { 
     IB details = new B(); 
     IB extDetails = new Bext(); 

     A instance1 = new A(details); 
     A instance2 = new A(extDetails); 
    } 
} 

這樣,您不需要通過創建Aext類來擴展繼承層次結構。您可以將其嚴格包含在所討論的屬性中。