2010-06-09 68 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()); 
    } 
} 

所以访问者模式给出了你可以在没有类型检查的情况下访问派生对象的成员。它有一点不灵活的模式(即需要知道前面访问哪些对象),但它可能适合您的需求。

相关问题