OOP C# Question: Making a Fruit a Pear
Given that I have an instance of Fruit with some properties set, and I want to get those properties into a new Pear instance (because this particular Fruit happens to have the qualities of a pear), what's the best way to achieve this effect?
For example, what we can't do is simply cast a Fruit to a Pear, because not all Fruits are Pears:
public static class PearGenerator {
public static Pear CreatePear () {
// Make a new generic fruit.
Fruit genericFruit = new Fruit();
// Upcast it to a pear. (Throws exception: Can't cast a Fruit to a Pear.)
Pear pear = (Pear)genericFruit;
// Return freshly grown pear.
return ( pear );
}
}
public class Fruit {
// some code
}
public class Pear : Fruit {
public void PutInPie () {
// some code
}
}
Thanks!
Update:
I don't control the "new Fruit()" code. My starting point is that I've got a Fruit to work with. I need to get that Fruit into a new Pear somehow. Maybe copy a开发者_StackOverflow社区ll the properties one by one?
Because the Fruit you've created isn't a Pear!
Edit: If you already have a Fruit
and need to create a Pear
from it then yes, you have no choice but to copy all the properties to a new Pear object. This should ideally be done inside a Pear
constructor that you create especially for that purpose.
It's not a pear. Try replacing your line
Fruit genericFruit = new Fruit();
with:
Fruit genericFruit = new Pear();
The downcast fails, because the instance created is a Fruit
, to make it a Pear
, change the code to
// Make a Pear - it looks like a fruit, tastes like a fruit,
// and quacks like a fruit. It must be a fruit.
Fruit genericFruit = new Pear();
// Downcast it to a pear.
Pear pear = (Pear)genericFruit;
Down-casting looks at the actual type, not the declared type - but you don't know what the actual type is (unless you test using is/as). This is why it's a little dangerous and most people try to avoid downcasting where possible.
EDIT: To make a fruit into a pear, you can create a new Pear yourself and initialize it as best you can. Some of the properites common to all fruit may be copied, from the fruit to the pear. But it may also be like trying to put a square peg into a round hole, mixing your metaphors and ending up with fruit puree.
A Pear is a Fruit.
Fruit is not necessarily a Pear.
If you're not responsible for Fruit
but are the author of Pear
, then maybe a different design would help:
It may be better to change your Pear
class to more of a FruitWrapper
class. This class would hold a reference to a Fruit
instead of being a more specific kind of Fruit
. It can have its own functionality (the reason you don't want to use Fruit
in the first place), and pass on fruit-type functionality to the Fruit
it's got inside. If it needs to work with library code that expects a Fruit
, just pass the one it's holding on to...
If Pear defined a load of new stuff.. and you created Fruit.
If you upcast Fruit to Pear what should all the extra stuff in Pear be set to?
It would all be undefined stuff. Hence why its not allowed!
When you're casting you're not actually changing any data, just the "label" if you will. If you have a Pear that was cast to a Fruit, then it can be cast back into a Pear, but if it was never a Pear to begin with, casting won't convert it into a Pear.
Is it absolutely necessary to inherit?
... I think the Pear -> fruit example is making this tough... this is an example right?
What about creating your Pear class like:
public class Pear {
public Fruit {get; set;}
public void Pear(add pear properties, Fruit fruit)
{
// assign pear properties
Fruit = fruit;
}
public void PutInPie () {
// some code
}
}
This may not be ideal but its an idea.
Good luck,
Patrick
Like Evgeny said what are doing is not legal because it is not typesafe. Downcasting a super type to a derived type if not allowed.
There are various ways to solve your problem, all depending on your situation
Generics, dynamic ( C# 4.0 only), Abstract classes, Interfaces.
You could create a new constructor for Pear that accepts an instance of Fruit.
This example reminds me of the one in this article. Take a look there at an interesting discussion of inheritance vs composition. Think about the fragile base class problem. To map from one object to the other, you can use AutoMapper.
精彩评论