2010-06-09 33 views
1

我想創建一個類,該類可以容納任意數量的相同類型的類。比如讓說,我有一個基類像如下:如何接受通用類並使用其屬性/方法

public class BaseClass 
{ 
    public string MyBaseString 
    { 
     get; 
     set; 
    } 
} 

然後,我有幾個派生類是這樣的:

public class DerivedClass : BaseClass 
{ 
    public MyDerivedClassString 
    { 
     get; 
     set; 
    } 
} 

public class DerivedClass2 : BaseClass 
{ 
    public MyDerivedClass2String 
    { 
     get; 
     set; 
    } 
} 

現在我想接受這些實現的一個類用它做東西。這是我能想到的唯一的事情,但必須有一個更好的辦法:

public class ClassA 
{ 
    public object MyClass 
    { 
     get; 
     set; 
    } 

    public ClassA (object myClass) 
    { 
     MyClass = myClass; 
     if (object is BaseClass) 
     { 
       //do something 
     } 
     else if (object is DerivedClass) 
     { 
      //do something specific to derived class 
     } 
     else if (object is DerivedClass2) 
     { 
      //do something specific to derived class 2 
     } 
    } 
} 

澄清:我想實現的具體目標是使用ClassA的作爲的各種實現容器類BaseClass的。我試圖完成的業務目標是創建一個Legend對象,它可以使用多種顏色方案(即Mono Color Ramp,Multi Color Ramp等)。因此,我希望Legend類包含正在使用的ColorScheme,但仍然可以訪問該顏色方案的獨特屬性以供稍後修改。

澄清2基於各種各樣的回答,我上了車,我想我提供什麼,我試圖做一個精確的複製:

public class BaseColorScheme 
    { 
     List<Color> _colors = new List<Color>();     
     public List<Color> Colors 
     { 
      get 
      { 
       return _colors; 
      } 
      set 
      { 
       _colors = value; 
      } 
     } 
} 

public class SingleColorScheme : BaseColorScheme 
{ 

     public Color MidColor 
     { 
      get; 
      set; 
     } 

     public SingleColorScheme(Color midColor, int numberOfClassifications) 
     { 
      Colors = CreateMonoColorRamp(midColor, numberOfClassifications); 
     } 
} 

public class MultiColorScheme : BaseColorScheme 
{ 
    public Color StartColor 
    { 
     get; 
     set; 
    } 
    public Color EndColor 
    { 
     get; 
     set; 
    } 
    public Color MidColor 
    { 
     get; 
     set; 
    } 

    public MultiColorScheme(Color startColor, Color endColor, Color midColor) 
    { 
     StartColor = startColor; 
     EndColor = endColor; 
     MidColor = midColor; 

     Colors = //do something to define multi color scheme 
    } 
} 

然後,我將有一個傳說級這將是像

public class Legend 
{ 
    public object ColorScheme 
    { get; set; } 

    public Guid LegendId 
    { get; set; } 

    public Legend(object colorScheme) 
    { 
      ColorScheme = colorScheme; 
    } 
} 

最後我可能有上顯示的各種配色方案的基礎上哪種類型的配色方案,它的性質傳說上面的一個形式。希望這有助於澄清一點。

+2

如果您不確定,我們應該如何確定? – SwDevMan81 2010-06-09 20:54:31

+0

這就是爲什麼我問這個問題。我對我的所有選項都不熟悉,所以我想我會詢問可能知道最佳實踐的用戶社區。 – 2010-06-09 20:56:04

+0

是的澄清更有意義。我想很多其他答案都是批評你的設計,而不是理解你想要的。 – SwDevMan81 2010-06-09 21:16:21

回答

5
public class ClassA<T> where T : BaseClass 
{ 
    public T MyClass { get; set; } 

    public ClassA(T myClass) { MyClass = myClass; } 
} 

除此之外,定義類層次結構的公共接口或者作爲一個接口或作爲基類內的方法(具體的,抽象的,或虛擬的)。然後你可以放心,所有派生類都有這樣的方法/屬性,並且可以在你的通用包裝中使用它們。

+0

我認爲這種方法將與Nate的附錄一起滿足我的需求。我可以看到的唯一問題是如果我需要傳入多個泛型類型會發生什麼。 – 2010-06-09 21:09:16

+0

如果您需要的不僅僅是一個BaseColorScheme,您只需引入其他類型參數: public class ColorSchemePatternLegend :LegendBase其中TColorScheme:ColorSchemeBase其中TPattern:PatternBase { } 等等...... – 2010-06-09 22:00:42

3

不要讓ClassA執行任何需要完成的任務,您可以使用多態性並讓類自己完成它。

只需在基類中聲明一個虛擬方法,讓它可以做任何您需要的操作,然後在子類中重寫此方法。在ClassA中的方法中,您只需將您接收的對象上的該方法作爲參數調用 - 而無需關心具體的類型。

+0

我可能沒有把這個清楚得足夠清楚,所以我很抱歉。我需要根據基類的實現來訪問不同的屬性。那有意義嗎? – 2010-06-09 21:00:25

+0

+1適用於一般OOP解決方案。 – Nate 2010-06-09 21:00:51

+0

@Blake:如果問題是讀取正確的屬性,只需製作一個返回正確屬性的虛擬方法即可。設置它是相似的:你也可以爲它聲明一個虛擬方法。如果你有更多的專業需求,那麼你應該更精確地瞭解這些類是如何不同的,以及你需要如何使用它們的方式有什麼不同。 – 2010-06-09 21:05:17

0

如果您需要訪問不同的屬性,根據其派生類傳遞這樣的事情應該有所幫助:

public class ClassA<T> where T : BaseClass 
{ 
    public T MyClass { get; set; } 

    public ClassA(T myClass) { MyClass = myClass; } 

    public void DoStuffToMyClass() 
    { 
     if(MyClass is BaseClass) 
     { // do base class stuff } 
     else if(Myclass is DerivedClass) 
     { // do DerivedClass stuff } 
     else if(MyClass is DerivedClass2) 
     { // do DerivedClass2 stuff } 
    } 
} 

這給你一個類型的安全性,以確保你至少有BaseClass的對象,可能是一個派生類。

+0

這是基於@Anthony Pegram的解決方案。 – Nate 2010-06-09 21:05:26

0

答案是多態,讓對象自己做。

public class BaseClass 
{ 
    public string MyString { get; set; } 

    public virtual string DoIt() 
    { 
    return "I'm Base Class"; 
    } 
} 

public class DerivedClassA 
{ 
    public override string DoIt() 
    { 
    return "I'm Derived Class A"; 
    } 
} 

public class DerivedClassB 
{ 
    public override string DoIt() 
    { 
    return "I'm Derived Class B"; 
    } 
} 
.... 
public ClassA (BaseClass myClass) 
{ 
    MyClass = myClass; 
    MyClass.DoIt(); 
} 
..... 
ClassA x1 = ClassA(new BaseClass()) // calls BaseClass.DoIt() 
ClassA x2 = ClassA(new DerivedClassA()) // calls DerivedClassA.DoIt() 
ClassA x3 = ClassA(new DerivedClassB()) // calls DerivedClassB.DoIt() 

每當你發現自己的演技不同的基於對象的運行時類型,你正在處理,打破OO原則,即代碼一個不尊重基類合同的類。

0

你可以使用虛擬方法嗎?

public abstract class BaseClass 
{ 
    public abstract void DoStuff(); 
} 
public class DerivedClass1 : BaseClass 
{ 
    public override void DoStuff() 
    { 
     ... 
    } 
} 
public class DerivedClass2 : BaseClass 
{ 
    public override void DoStuff() 
    { 
     ... 
    } 
} 

沒有泛型:

public class ClassA 
{ 
    public BaseClass MyClass 
    { 
     get; 
     set; 
    } 

    public ClassA (BaseClass myClass) 
    { 
     MyClass = myClass; 
     myClass.DoStuff(); 
    } 
} 

或使用泛型:

public class ClassA<T> where T : BaseClass  
{  
    public T MyClass { get; set; }  

    public ClassA (T myClass) 
    { 
     MyClass = myClass; 
     myClass.DoStuff(); 
    } 
} 
0

保持簡單:多態

希望您的對象都有一個共同的接口,是這樣的:

class Base { 
    public virtual void DoSomething() { /* Default implementation */ } 
} 

class Derived1 : Base { 
    public override void DoSomething() { /* Implementation specific to this type */ } 
} 

class Derived2 : Base { 
    public override void DoSomething() { /* Another implementation specific to this type */ } 
} 

也許他們實現了一個通用接口。所以希望您的消費類可容納你輸入儘可能最普遍的代表性和調用代碼,例如:

class Dependent { 
    public Dependent(Base instance) { 
     instance.DoSomething(); 
    } 
} 

所以,你的依賴類並不真的是它是否有一個派生類型或基本類型。

沒有這麼簡單:訪問者模式

有時多態性並未真正發揮作用,如果你需要訪問你的派生類的特殊成員,這些成員都沒有在特別的情況下基類。在這種情況下訪問者模式效果很好,特別是如果你有一個固定的,明確定義的對象圖。

public interface IVisitor<T> { 
    T Visit(Base x); 
    T Visit(Derived1 x); 
    T Visit(Derived2 x); 
} 

class Base { 
    public virtual T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); } 
    public string BaseString { get; set; } 
} 

class Derived1 : Base { 
    public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); } 
    public string Derived1String { get; set; } 
} 

class Derived2 : Base { 
    public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); } 
    public string Derived2String { get; set; } 
} 

所以Derived1Derived2有一組不同的屬性,如果你需要得到這些屬性沒有運行時類型檢查,落實訪問者:

class DefaultStringVisitor : IBaseVisitor<string> { 
    public string Visit(Base x) { return x.BaseString; } 
    public string Visit(Derived1 x) { return x.Derived1String; } 
    public string Visit(Derived2 x) { return x.Derived2String; } 
} 

class Dependent { 
    public Dependent(Base x) { 
     string whatever = x.Accept<string>(new DefaultStringVisitor()); 
    } 
} 

所以訪問者模式給出了你可以在沒有類型檢查的情況下訪問派生對象的成員。它有一點不靈活的模式(即需要知道前面訪問哪些對象),但它可能適合您的需求。

相關問題