views:

139

answers:

4

I was wondering how to do this, consider the following classes

public class Fruit
{
    public string Name { get; set; }
    public Color Color { get; set; }
}
public class Apple : Fruit
{
    public Apple()
    {

    }
}

How can I instantiate a new fruit but upcast to Apple, is there a way to instantiate a bunch of Fruit and make them apples with the name & color set. Do I need to manually deep copy?

Of course this fails

Fruit a = new Fruit();
a.Name = "FirstApple";
a.Color = Color.Red;
Apple wa = a as Apple;
System.Diagnostics.Debug.Print("Apple name: " + wa.Name);

Do I need to pass in a Fruit to the AppleCTor and manually set the name and color( or 1-n properties) Is there an better design to do this?

+2  A: 

It looks like you're trying to come up with a way to instantiate one of many possible objects derived from a common base class. Typically this is done through the Abstract Factory pattern. For more details and implementation examples see: http://en.wikipedia.org/wiki/Abstract_factory_pattern

Scott J
What's wrong with this answer? I thought it'd be a good resource for the OP.
dash-tom-bang
Answers that are just links are frowned upon.
John Saunders
That's a fair cop. Relatively new here, apologies.
Scott J
+1 good link (everyone here links to sites)
PostMan
+1 for the edit.
SnOrfus
+6  A: 

By default, the a instance is an instance of Fruit and is not convertible to Apple. It's not an Apple instance, and will never be.

You can, however, implement an explicit cast.

Mark Seemann
+2  A: 

If you create a Fruit, it isn't an Apple. You can't upcast it, because it probably won't have all of the attributes that it'll need. If you want an Apple, create an Apple. You don't need to pass anything to anything.

I suspect the following will work:

Fruit a = new Apple();
System.Diagnostics.Debug.Print("Apple name: " + a.Name);

...but I'm not a Java programmer. That's basically what you'd do in C++ though. (Be sure to read the Abstract Factory Pattern link given in another answer, especially if you need to instantiate a bunch of different subtypes of Fruit.)

dash-tom-bang
+4  A: 

In your model, a Fruit is not an Apple - if you want an Apple, instantiate one. Alternatively, if you want to create an Apple using a Fruit as a starting point, create a constructor for Apple that can accept a Fruit.

You should note, that object models where intermediate classes in the inheritance hierarchy are instantiable (not abstract) is often a bad idea. In some cases, such hierarchies may be appropriate - but I've found that in general they are more trouble than they are worth. Think really hard about whether both Fruit and Apple need to be concrete and instantiable.

LBushkin
I tried that, it didn't seem right, which says to me this should be redesigned public Apple(Fruit fruit) { base.Color = fruit.Color; //etc }
Eric