2011-10-29 53 views
4

我有2個班,每個收益本身的所有功能:C#面向對象的返回類型「這個」兒童通話

public class Parent{ 
    public Parent SetId(string id){ 
     ... 
     return this 
    } 
} 

public class Child : Parent{ 
    public Child SetName(string id){ 
     ... 
     return this 
    } 
} 

我想啓用這種API的:

new Child().SetId("id").SetName("name"); 

SetName無法訪問,因爲SetId返回ParentSetNameChild上。

怎麼樣?

+0

@ L.B - 家長可以有許多孩子...... – SexyMF

+0

@ L.B這是錯誤的,因爲您不知道在您寫入父類時您將擁有多少個孩子類, –

+0

如果你沒有引用Child類,你的(Child)將不會編譯。如果孩子不在編譯時間... –

回答

8

如果你真的想這樣流暢的行爲,並Parent類可以進行抽象,那麼你可以實現這樣的:

public abstract class Parent<T> where T : Parent<T> 
{ 
    public T SetId(string id) { 
     return (T)this; 
    } 
} 

public class Child : Parent<Child> 
{ 
    public Child SetName(string id) { 
     return this; 
    } 
} 

現在可以這樣寫:

new Child().SetId("id").SetName("name"); 
+0

+1比我的想法更好:)我知道會有一種方法來使用泛型,但它並沒有跨越我的想法。 – dowhilefor

+0

呃呃,比我更快,更聰明,因爲你有解決方案。因爲它在這裏是在java中完成的:http://stackoverflow.com/questions/4031857/way-to-make-java-parent-class-method-return-object-of-child-class/4032924#4032924 +1 from我;-) –

+0

@Davide Piras:Eric Lippert寫了一篇關於這些通用結構的有趣文章:http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx –

0

Davide Piras是對的,一種方法是使用虛擬方法或更好的界面。

看到這個代碼

public interface INode 
{ 
    INode SetName(string aName); 
    INode SetId(string aId); 
} 

public class Parent : INode 
{ 
    public virtual INode SetId(string id) 
    { 
     ... 
     return this 
    } 

    public virtual INode SetName(string aId) 
    { 
     return this; 
    } 
} 

public class Child : Parent 
{ 
    public override INode SetName(string id) 
    { 
     ... 
     return this; 
    } 
} 
+0

所以我需要插入一個接口,將有所有的孩子的方法? (我的意思是返回這個的方法),但問題在於不正確地將一個Chid方法暴露給其他Child,即使它們不相關。 – SexyMF

0

它看起來像你想創建一個fluent interface。你確定這將是開發者使用這些類最簡單的方法嗎?

如何使用簡單的舊屬性爲'名稱'和'Id'?這很好用,尤其是在使用Collection Initialiser語法時。

+0

美麗的,他們可以使用流利或一個一個... – SexyMF

3

我可能會錯過這裏的觀點,但它看起來像只是試圖設置屬性。如果您將它們公開爲屬性,則可以使用object initializer call

var child = new Child() 
{ 
    Id = value1; 
    Name = value2; 
} 

你也可以調用一個方法,而不是在初始化器中設置一個值。

0

我發現了一個類似的問題,但對於Java語言在這裏:Way to make Java parent class method return object of child class

試圖編譯它,但不起作用,看到我剪斷,看到我的COM基本上看起來像在Java中,我們現在可以將它轉換爲T,但在C#中。有趣的...

(這不是你的問題的解決方案我只是報告我試圖做什麼,我能得到多遠,如果有人知道一些神奇的工作,讓這種設計保持這種設計.. 。歡迎:))

class Program 
{ 
    static void Main(string[] args) 
    { 
     var obj = new Child().SetId("id").SetName("aaa"); 
    } 
} 

public class Parent<T> 
{ 
    public virtual T SetId(string id) 
    { 
     // this does not work 
     return (T)this; 

     // this compiles but is NOT what we want :(
     //return default(T); 
    } 
} 

public class Child : Parent<Child> 
{ 
    public Child SetName(string name) 
    { 
     return this; 
    } 
} 
1

我覺得很奇怪,你想從當前實例中返回一個類的當前實例的引用。你會不會有這樣的參考,爲了訪問對象的屬性和方法?你可能在想克隆嗎?

除非我錯過了一些關於你的模型的東西,看起來好像建立了一個初始化方案,一些無聊的Property定義,或許還有一個工廠類可能更像你正在尋找的東西。您似乎也可能考慮將您的父母設爲ID作爲不可變屬性,儘管您的要求可能會爲此創建一個真實的原因。

這裏有一些可能有用的類def。現在在聖路易斯早些時候,我還沒有適當地氣候,所以我可能會錯過一些東西。 。 。 ;-)

家長:

public class Parent 
{ 

    protected string _id; 

    // Protected default constructor so tht this class can be inherited: 
    protected Parent() { } 

    // REquired to set ID at initialization; 
    public Parent(String ID) 
    { 
     _id = ID; 
    } 

    // Read-only: 
    public String ID 
    { 
     get { return _id; } 
    } 


    // This seems a little dodgy. Why would you want to return a reference 
    // to the current instance as a result of resetting the ID? 
    public Parent SetID(String ID) 
    { 
     _id = ID; 
     return this; 
    } 
} 

家長廠:

public class ParentFactory 
{ 
    public static Parent NewParent(String ID) 
    { 
     Parent newParent = new Parent(ID); 
     return newParent; 
    } 
} 

的孩子:

public class Child : Parent 
{ 

    private string _name; 

    // Protected default constructor so tht this class can be inherited: 
    protected Child() { } 

    // Initialize a new Child with the ID property required for the parent: 
    public Child(String ID) 
    { 
     base.SetID(ID); 
    } 


    // Initialize a new child with both properties set: 
    public Child(String ID, String Name) : this(ID) 
    { 
     _name = Name; 
    } 

    // This could be read-only as well: 
    public String Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 


    // Again, seems kinda dodgy: 
    public Child SetName(String name) 
    { 
     return this; 
    } 
} 

一個孩子廠:

public class ChildFactory 
{ 
    public static Child NewChild(String ID) 
    { 
     Child newChild = new Child(ID); 
     return newChild; 
    } 


    public static Child NewChild(String ID, String Name) 
    { 
     Child newChild = new Child(ID, Name); 
     return newChild; 
    } 
} 
0

這是什麼問題: ((Child)(new Child()。SetId(「id」))。SetName(「name」);

這裏的解釋是,雖然對象的運行時類型是Child,但編譯您希望支持的表達式時,靜態類型推斷C#使用的是斷定SetId(「id」)的靜態類型爲Parent。它是,因爲SetId是在Parent類中定義的。

事實上,你的對象是Child類型的,並且有一個SetName方法。因此,SetName可供您使用,但前提是您告訴C#將對象視爲Child。在你的表達中,你不需要,但是因爲Parent沒有SetName方法,所以你的代碼不會被檢查,所以它不會被編譯。

如果你這樣做了,C#會檢查這個類型以防萬一,但是它會執行你想要的調用。