Inheritance question: How to instantiate derived class from base class

A

Anthony Greene

This is probably a very introductory object-oriented question, but it
has been nagging me for years, and since I've never been able to find
the right answer, I've had to work around it with non-optimal code.
However, I suspect there must be a proper object-oriented approach to
solving this problem. Perhaps someone might be able to help me out.

Oftentimes I need to convert an object declared as a base type into a
object of one of its derived classes. Here is an example of my non-
optimal code (what I am doing now). Imagine that
both the base class and derive class are much more complicated than
this with dozens of properties.

/********/

class Shape : System.Object
{
public decimal XCoordinate;
public decimal YCoordinate;
}

class Circle : Shape
{
public decimal Circumference;
}



void main ()
{
//declare a new variable of type Shape
Shape MyShape = new Shape();
MyShape.XCoordinate = 99;
MyShape.YCoordinate = 99;

//various programming steps
// ...

//I now decide i need MyShape to be of type Circle
Circle MyCircle = new Circle();

//copy all properites of MyShape into MyCircle
MyCircle.XCoordinate = MyShape.XCoordinate;
MyCircle.YCoordinate = MyShape.YCoordinate;
MyCircle.Circumference = 500;
}

/********/

What I need to know is what is the best way to create a new Circle
object which is an exact copy of all properties of MyShape.
Obviously, copying all properties over from one to the other is not
ideal, because if later I add new properties of the Shape class, I
would want its values copied over to MyCircle, without updating the
above code.

When I try to execute a line like:

MyCircle = (Circle)MyShape;

That obviously does not work, and throws a runtime error: "A first
chance exception of type 'System.InvalidCastException' occurred".
However, I am sure there must be a proper approach to this, other than
manually creating a new instance and copying over each and every
property.

Thank you for your help.
 
P

Peter Bradley

I'm assuming that you cannot, for some reason, know in advance that you want
your shape to be a Circle. If that were the case you could declare it as a
Circle in the first place and just treat it as a Shape until you need it to
be a Circle (e.g. in Arrays of type Shape).

With the above assumption, the best solution I know of is to have a
conversion function in Circle:

public Circle ConvertFromShape(Shape shape)
{
Circle c = new Circle();
c.XCoordinate = shape.XCoordinate;
c.YCoordinate = shape.YCoordinate;
return c;
}

Now, when you need to convert a Shape to a Circle, you can do:

Shape s = new Shape();
....
....
Circle c = c.ConvertFromShape(s);
....
....

Or you might make it static, of course. And you can make the code above
even prettier with good use of constructors: but I assume you don't need me
to tell you that.

It's probably no more efficient, but it is a bit prettier.

HTH


Peter
 
S

Stefan Hoffmann

hi Anthony,

Anthony said:
What I need to know is what is the best way to create a new Circle
object which is an exact copy of all properties of MyShape.
I would use some kind of "copy" constructor, not tested:

class Shape
{
public void CopyTo(Shape toShape) {}
}

class Circle : Shape
{
public Circle() {};
public Circle(Shape fromShape) { fromShape.CopyTo((Shape)this) };
public decimal Circumference;
}

When changing properties of Shape you just have to change the CopyTo()
method.


mfG
--> stefan <--
 
T

Tom Porterfield

Anthony said:
This is probably a very introductory object-oriented question, but it
has been nagging me for years, and since I've never been able to find
the right answer, I've had to work around it with non-optimal code.
However, I suspect there must be a proper object-oriented approach to
solving this problem. Perhaps someone might be able to help me out.

Oftentimes I need to convert an object declared as a base type into a
object of one of its derived classes. Here is an example of my non-
optimal code (what I am doing now). Imagine that
both the base class and derive class are much more complicated than
this with dozens of properties.

/********/

class Shape : System.Object
{
public decimal XCoordinate;
public decimal YCoordinate;
}

class Circle : Shape
{
public decimal Circumference;
}



void main ()
{
//declare a new variable of type Shape
Shape MyShape = new Shape();
MyShape.XCoordinate = 99;
MyShape.YCoordinate = 99;

//various programming steps
// ...

//I now decide i need MyShape to be of type Circle
Circle MyCircle = new Circle();

//copy all properites of MyShape into MyCircle
MyCircle.XCoordinate = MyShape.XCoordinate;
MyCircle.YCoordinate = MyShape.YCoordinate;
MyCircle.Circumference = 500;
}

/********/

What I need to know is what is the best way to create a new Circle
object which is an exact copy of all properties of MyShape.
Obviously, copying all properties over from one to the other is not
ideal, because if later I add new properties of the Shape class, I
would want its values copied over to MyCircle, without updating the
above code.

When I try to execute a line like:

MyCircle = (Circle)MyShape;

That obviously does not work, and throws a runtime error: "A first
chance exception of type 'System.InvalidCastException' occurred".
However, I am sure there must be a proper approach to this, other than
manually creating a new instance and copying over each and every
property.

Thank you for your help.

You could do it using reflection, but there's a reason this type of stuff
isn't easy, it's usually not a good idea and certainly not nearly as simple
as your Circle/Shape example. If you want to be able to create a Circle
from a Shape, you should be explicit in how that is done, meaning clearly
stating which properties of Shape get copied to Circle and how. You can
make this easier on consumers of Circle by giving Circle a non-default
constructor which takes in an instance of Shape, thus allowing the consumer
to write Circle MyCircle = new Circle(MyShape);. But within that
constructor you'll be manually setting the properties of Circle from Shape
as are appropriate. In your simplistic example it may not be clear why it's
not a good idea to have this type of construction be automatic. There are
many real-world examples where automating this type of object construction
would cause problems.

If you are sure you always want the properties from your base Shape copied
directly, you could use a variation on the above. That would be to give
Shape a copy constructor, and have the Circle constructor that takes in a
Shape delegate that to the base Shape object. Ex:

public class Shape
{
public decimal X;
public decimal Y;

public Shape() {}
public Shape(Shape shape)
{
this.X = shape.X;
this.Y = shape.Y;
}
}

public class Circle
{
public decimal C;

public Circle(){}
public Circle(Shape shape) : base (shape) {}
public Circle(Circle circle) : base (circle)
{
this.C = circle.C;
}
}
 
L

Laura T.

Copy constructor. http://en.wikipedia.org/wiki/Copy_constructor

Like:

class Shape
{
public decimal XCoordinate;
public decimal YCoordinate;

public Shape() { }

protected Shape(Shape copyshape)
{
XCoordinate = copyshape.XCoordinate;
YCoordinate = copyshape.YCoordinate;
}
}

class Circle : Shape
{
public decimal Circumference;

public Circle(Shape shape) : base(shape)
{
Circumference = 1.0m;
}
}

static void Main(string[] args)
{
Shape newShape = new Shape();
Circle newCircle = new Circle(newShape);

}

Cicle does not need to know anything about shape. Free to extend as you
like.
 
T

Tom Porterfield

Laura said:
class Shape
{
public decimal XCoordinate;
public decimal YCoordinate;

public Shape() { }

protected Shape(Shape copyshape)
{
XCoordinate = copyshape.XCoordinate;
YCoordinate = copyshape.YCoordinate;
}
}

class Circle : Shape
{
public decimal Circumference;

public Circle(Shape shape) : base(shape)
{
Circumference = 1.0m;
}
}

Cicle does not need to know anything about shape. Free to extend as you
like.

Interesting comment that Circle does not need to know anything about shape
in light of the fact that Circle is a Shape and therefore knows a lot about
Shape.
 
B

Brian Gideon

This is probably a very introductory object-oriented question, but it
has been nagging me for years, and since I've never been able to find
the right answer, I've had to work around it with non-optimal code.
However, I suspect there must be a proper object-oriented approach to
solving this problem. Perhaps someone might be able to help me out.

Oftentimes I need to convert an object declared as a base type into a
object of one of its derived classes. Here is an example of my non-
optimal code (what I am doing now). Imagine that
both the base class and derive class are much more complicated than
this with dozens of properties.

/********/

class Shape : System.Object
{
public decimal XCoordinate;
public decimal YCoordinate;

}

class Circle : Shape
{
public decimal Circumference;

}

void main ()
{
//declare a new variable of type Shape
Shape MyShape = new Shape();
MyShape.XCoordinate = 99;
MyShape.YCoordinate = 99;

//various programming steps
// ...

//I now decide i need MyShape to be of type Circle
Circle MyCircle = new Circle();

//copy all properites of MyShape into MyCircle
MyCircle.XCoordinate = MyShape.XCoordinate;
MyCircle.YCoordinate = MyShape.YCoordinate;
MyCircle.Circumference = 500;

}

/********/

What I need to know is what is the best way to create a new Circle
object which is an exact copy of all properties of MyShape.
Obviously, copying all properties over from one to the other is not
ideal, because if later I add new properties of the Shape class, I
would want its values copied over to MyCircle, without updating the
above code.

When I try to execute a line like:

MyCircle = (Circle)MyShape;

That obviously does not work, and throws a runtime error: "A first
chance exception of type 'System.InvalidCastException' occurred".
However, I am sure there must be a proper approach to this, other than
manually creating a new instance and copying over each and every
property.

Thank you for your help.

Hi,

I'm thinking of three possibilities.

1) Define a static factory method on Circle called Transorm. That
method would have the logic required to transform any Shape into a
Circle. The Circle contains the logic in this case.

2) Define a virtual instance method on Shape called ToCircle. That
method would have the logic required to transform that particular
Shape into a Circle. Each individual Shape contains the logic in this
case.

3) If there are a lot of shapes in the inheritance hierarchy and you
want to be able to do different kinds of transormations then you may
want to abstract this logic into a separate class or class hierarchy.

Brian
 
A

Anthony Greene

Thank you for your quick and helpful answers.

This is exactly how it's been explained to me previously, and most
times how I have implemented the solution (either using a factory
pattern, or more often, a constructor)

public Circle (Shape baseShape)
{
//etc.
}

For the concerns I outlined above, I was never 100% happy with this
implementation, and thought it there might be a simple object-oriented
construct I was missing that would let me cast the base class as the
derived class. I see now that it's not possible.

I would much prefer not getting into using Reflection for a problem
like this, because I don't believe that 90% of the cases that the
overhead of using Reflection would be worth writing out the code
manually.

Thank you again.
 
P

PS

Anthony Greene said:
This is probably a very introductory object-oriented question, but it
has been nagging me for years, and since I've never been able to find
the right answer, I've had to work around it with non-optimal code.
However, I suspect there must be a proper object-oriented approach to
solving this problem. Perhaps someone might be able to help me out.

Oftentimes I need to convert an object declared as a base type into a
object of one of its derived classes. Here is an example of my non-
optimal code (what I am doing now). Imagine that
both the base class and derive class are much more complicated than
this with dozens of properties.

/********/

class Shape : System.Object
{
public decimal XCoordinate;
public decimal YCoordinate;
}

class Circle : Shape
{
public decimal Circumference;
}



void main ()
{
//declare a new variable of type Shape
Shape MyShape = new Shape();
MyShape.XCoordinate = 99;
MyShape.YCoordinate = 99;

//various programming steps
// ...

//I now decide i need MyShape to be of type Circle
Circle MyCircle = new Circle();

//copy all properites of MyShape into MyCircle
MyCircle.XCoordinate = MyShape.XCoordinate;
MyCircle.YCoordinate = MyShape.YCoordinate;
MyCircle.Circumference = 500;
}

/********/

What I need to know is what is the best way to create a new Circle
object which is an exact copy of all properties of MyShape.
Obviously, copying all properties over from one to the other is not
ideal, because if later I add new properties of the Shape class, I
would want its values copied over to MyCircle, without updating the
above code.

When I try to execute a line like:

MyCircle = (Circle)MyShape;

That obviously does not work, and throws a runtime error: "A first
chance exception of type 'System.InvalidCastException' occurred".
However, I am sure there must be a proper approach to this, other than
manually creating a new instance and copying over each and every
property.
see http://en.wikipedia.org/wiki/Prototype_pattern
 
T

Tom Porterfield

PS said:

The prototype pattern doesn't solve this problem. He wants to be able to
create a derived object based on an instance of a base object. Prototype is
used to create the same type of object from an existing instance of the same
type of object, not from a base or derived object. Typically you'll see
prototype used when instantiation of a new object is more expensive than
copying an existing object, or in conjunction with a factory pattern when
you want to abstract away from the client the complexity of knowing exactly
what type of object to create.
 
M

Mark Wilden

Anthony Greene said:
Oftentimes I need to convert an object declared as a base type into a
object of one of its derived classes.

You shouldn't need to do this often.

///ark
 
P

PS

Tom Porterfield said:
The prototype pattern doesn't solve this problem. He wants to be able to
create a derived object based on an instance of a base object. Prototype
is used to create the same type of object from an existing instance of the
same type of object, not from a base or derived object. Typically you'll
see prototype used when instantiation of a new object is more expensive
than copying an existing object, or in conjunction with a factory pattern
when you want to abstract away from the client the complexity of knowing
exactly what type of object to create.

My bad!!. Never had any reason to cast from base to derived so never looked
into any pattern for this in detail. I skimmed the prototype code and
thought it looked in the ball park a little but after looking at it in more
detail I can see it would not do what he wanted.

PS
 
C

Chris Nahr

You shouldn't need to do this often.

I second that. Converting an object that was instantiated as a base
type into a derived type should happen extremely rarely, if at all.
You should restructure your program so that you know precisely what
type you need at the time of instantiation.
 
P

Peter Bradley

And I third it.

Peter


Chris Nahr said:
I second that. Converting an object that was instantiated as a base
type into a derived type should happen extremely rarely, if at all.
You should restructure your program so that you know precisely what
type you need at the time of instantiation.
 
P

PS

Mark Wilden said:
You shouldn't need to do this often.

If you could cast a base object to a derived object wouldn't that mean that
you could cast any object to any other type of object because all objects
share the same base which is "object". This would be the end of type safety
as I see it.

PS
 
P

PS

Anthony Greene said:
Thank you for your quick and helpful answers.

This is exactly how it's been explained to me previously, and most
times how I have implemented the solution (either using a factory
pattern, or more often, a constructor)

public Circle (Shape baseShape)
{
//etc.
}

For the concerns I outlined above, I was never 100% happy with this
implementation, and thought it there might be a simple object-oriented
construct I was missing that would let me cast the base class as the
derived class. I see now that it's not possible.

I would much prefer not getting into using Reflection for a problem
like this, because I don't believe that 90% of the cases that the
overhead of using Reflection would be worth writing out the code
manually.

Except that using Relection would be self maintaining.

You could also look into the Decorator pattern which is not what you asked
about but might solve your problem. Although this pattern also comes with a
similar "maintenance" issue.

PS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top