2016-07-30 159 views
-1

我有一个情况我有被用作占位符来实例化一个派生类对象...例如一个抽象基类对象...C#实例化一个基础对象作为派生对象

public abstract class Fruit(){ //stuff} 

public class Banana() : Fruit(){ //stuff } 

public class Apple() : Fruit(){ //stuff } 

public class FruitSalad() 
{ 
Fruit SomeKindOfFruit; 
public DoStuff(Fruit frt) 
{ 
    SomeKindOfFruit = new ????? 
} 
} 

所以,该功能将接受水果...该程序不知道什么样的水果......可能是一个苹果......可能是一个香蕉......可能是一个猕猴桃......但我需要它采取输入frt,然后告诉SomeKindOfFruit,“嘿.. frt是一个苹果,所以你现在是一个苹果”。我知道SomeKindOfFruit = new Apple();工作......但我不想要做的是必须硬编码一堆if/then语句或开关来评估类型,然后显式声明每个可能的派生类......派生类派生类类...派生类的派生类... ad nauseum ...特别是因为即使这样做,我也必须拉类型来评估它,并且它会更容易,“看到这个派生的东西?无论这件事是什么,你现在都是那种类型的东西”。只需要一段代码,我就可以创建尽可能多的派生类,并且它会继续工作;我不必一再重复添加更多评估。

[编辑]

这就是我想......我起初试图只是做一个简单的公式等于......这会引发空引用异常。好吧,我实际上做的与水果无关,但这是描述问题而不迷失在杂草中的最简单方式。实际的程序正在做的是我有2个类......好吧,一个运行GUI组件的类以及一组类(基类+派生类),这些类是在引擎盖下和在网络。在这些类中,我创建了一个对象,理论上它应该引用彼此。顺序是从存储的SQL数据创建数据类。一旦创建了所有数据,我在数据类中创建了一个方法来创建将在GUI上显示它的图形类。部分原因是数据类应该让图形类对自身进行反射,以便两个类都可以引用另一个类,并且信息可以通过两种方式实现......我可以通过图形组件将信息发送到相关数据中类和数据类可以从网上获取信息并以图形形式显示它

public abstract class baseData() { 
public graphicClass GraphicRepresentation; 

    public baseData(stuff){ 
    //Sets all the relevant data 
    } 

    public void Activate(){ 
    GraphicRepresentation = new graphicClass(); 
    //Sets all the relevant components in the class 
    GraphicRepresentation.DataReference = this; 
    }` 
    } 

上面的代码抛出一个空引用异常。我唯一能想到的是DataReference,它是一个baseData对象,在我可以给它分配“this”之前需要实例化,但我不能实例化一个抽象类,所以我必须能够实例化它因为任何派生类型“this”在我能使它等于“this”之前。

+0

'SomeKindOfFruit = frt' ????不太清楚为什么这不起作用。 –

+0

如果您发现问题,请不要破坏您的问题。只需在评论中解释您的发现并将您的问题标记为脱离主题 - >错字。我回到你原来的问题。 – honk

+0

由于OP在[本次修订](http://stackoverflow.com/revisions/38669603/3)中的解释,我投票结束为错字。 – honk

回答

2

你可以让你的方法一般:

public class FruitSalad() 
{ 
    Fruit SomeKindOfFruit; 

    public DoStuff<TFruit>(TFruit frt) 
     where TFruit : Fruit, new() 
    { 
     SomeeKindOfFruit = new TFruit(); 
    } 
1

我认为你缺少了这一点。

首先,您的DoStuff方法建议temporary field code smell。类字段意味着在构造函数中初始化,而不是在方法中初始化。如果我要实现FruitSalad类,我可能会写这样的:

public class FruitSalad 
{ 
    private readonly Fruit _fruit; 

    public FruitSalad(Fruit fruit) 
    { 
     _fruit = fruit; 
    } 

    public DoStuff() 
    { 
     // Act on the _fruit field 
    } 
} 

其次,不要紧,什么是Fruit实际运行时类型传递到的FruitSalad只要构造/ DoStuff方法因为它来源于Fruit。这是polymorphism

例如,如果有在Fruit是一个abstract方法CutToPieces像:

public abstract class Fruit 
{ 
    public abstract void CutToPieces(); 
} 

AppleBanana正在执行这样的:

public class Apple : Fruit 
{ 
    public override void CutToPieces() 
    { 
     Console.WriteLine("Apple being diced"); 
    } 
} 

public class Banana : Fruit 
{ 
    public override void CutToPieces() 
    { 
     Console.WriteLine("Banana being cut to small pieces"); 
    } 
} 

FruitSalad仍然可以在不知道实际的制备正在传入的Fruit实例的运行时类型:

public class FruitSalad 
{ 
    private readonly Fruit _fruit; 

    public FruitSalad(Fruit fruit) 
    { 
     _fruit = fruit; 
    } 

    public DoStuff() 
    { 
     // Prints "Apple being diced" or "Banana being cut to small pieces" 
     // depending on the runtime type of `Fruit` being passed into the 
     // constructor of FruitSalad 
     _fruit.CutToPieces(); 
    } 
} 
+0

我增加了更多信息。 –

0

的CLR已经有这样的设施:

void GetFruitType(Fruit fruit) 
{ 
    Type t = fruit.GetType(); 
    if (t.Equals(typeof(Apple))) HandleApple(); 
} 

但是,如果你想避免处理的猜测,并通过各类开关,你应该用的组合物,而不是继承:

interface IFruit 
{ 
    void CutFruit(); 
} 


class Apple : IFruit 
{ 
    public void IFruit.CutFruit() 
    { 
     // Implementation for apple 
     // For fruits that do not support cutting, you still need to 
     // implement the interface, but you can throw a NotSupportedException 
     // and then catch the exception in the FruitSalad class 
    } 
} 

class Grape : IFruit 
{ 
    public void IFruit.CutFruit() 
    { 
     throw new NotSupportedException("You don't cut grapes..."); 
    } 
} 

class FruitSalad 
{ 
    IFruit[] _fruits = null; // Initialize in constructor or through property 

    void CutFruits() 
    { 
     foreach (IFruit fruit in _fruits) 
     { 
      try 
      { 
       fruit.CutFruit(); 
      } 
      catch (NotSupportedException ex) 
      { 
       Debug.Print(ex.Message); 
      } 
     } 
    } 
} 

组合看起来像是一个更好的选择,它缩短了继承链并在派生类中保留了特定于水果的实现。单一职责原则和所有这一切。