Initializing a class

I

Ikke

Hi everybody,

Suppose I have a class 'Dog' defined as follows:
public class Dog : Animal

Now suppose I have the following code:
Dog fido = null;
Animal animal = new Animal();

Then how do I assign the animal Object to fido?

If I were to write:
fido = (Animal) animal;
I get an error in Visual Studio and the project does not compile.

If I write:
fido = (Dog) animal;
then the code compiles, but I get a runtime exception (invalid class cast).

What I'm looking for, is a way to get the following:

public class Dog
{
public Dog(Animal animal)
{
// super(animal);
}
}

The super(animal) call is invalid, of course, but is there a way to
initialize the new Dog Object to contain the known values of animal?

Thanks in advance,

Ikke
 
M

Marina Levit [MVP]

You can't do this. A dog is an animal, but an animal isn't a dog.

This means that the following is ok:

Dog fido = new Dog;
Animal animal = fido;

But what you have:

Animal animal = new Animal;
Dog fido = animal;

is not.

I am not sure why the constructor for Dog would receive a different animal
as the constructor? Why would it need a completely different animal to
initialize itself?

What about something like:

public Dog():base()
{
// dog specific initialization here
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Ikke said:
Hi everybody,

Suppose I have a class 'Dog' defined as follows:
public class Dog : Animal

Now suppose I have the following code:
Dog fido = null;
Animal animal = new Animal();

Then how do I assign the animal Object to fido?

If I were to write:
fido = (Animal) animal;
I get an error in Visual Studio and the project does not compile.

If I write:
fido = (Dog) animal;
then the code compiles, but I get a runtime exception (invalid class
cast).

I think Marina explain this already.
What I'm looking for, is a way to get the following:

public class Dog
{
public Dog(Animal animal)
{
// super(animal);
}
}

The super(animal) call is invalid, of course, but is there a way to
initialize the new Dog Object to contain the known values of animal?

What you can do is create a constructor that receive an Instace of Animal ,
inside the constructor you assign the values of the new instance being
created based on the same values of the instance used as parameter.

public class Animal
{
protected int numberLegs;
public Animal()
{
numberLegs=4;
}
protected Animal(Animal animal)
{
this.numberLegs = animal.numberLegs;
}
}

public class Dog:Animal
{
public Dog(Animal animal):base(animal)
{

}
}


Will that work for you?
 
I

Ikke

You can't do this. A dog is an animal, but an animal isn't a dog.

This means that the following is ok:

Dog fido = new Dog;
Animal animal = fido;

But what you have:

Animal animal = new Animal;
Dog fido = animal;

is not.

I am not sure why the constructor for Dog would receive a different
animal as the constructor? Why would it need a completely different
animal to initialize itself?

What about something like:

public Dog():base()
{
// dog specific initialization here
}

Thanks for the reply!

The classes I'm working with are more elaborate than Dog and Animal, and
that is precisely my problem.

I have a provider which returns an Animal Object - in my case, an Object
with lots of int codes.

My Dog Object then, must contain both the codes, and the translation of
those codes. Therefor, Dog inherits from Animal and adds the pieces
needed for those code translations.

So I was thinking along the lines of a constructor like the following:
public Dog(Animal animal)
{
// here I copy every property from animal to the new dog Object
}

But this would mean copying a lot of fields, which is cumbersome and
errorprone. Surely there must be a simpler way?

Any ideas?

Ikke
 
S

sloan

That's what I think is called a "object proxy"


http://www.dofactory.com/Patterns/PatternProxy.aspx


public class Dog
private m_animal
public Dog (Animal an )
this.m_animal = an;


public string Name
{get { return this.m_animal.Name ; }}


Try that out. I think its better to keep an internal copy of your Animal
(m_animal) than to .. "map" all the properties over to internal member
variables.

That why , you don't have to really keep tracking of sync'ing up...because
you'll return the property of m_animal.

...
 
J

Jon Skeet [C# MVP]

Ikke said:
The classes I'm working with are more elaborate than Dog and Animal, and
that is precisely my problem.

I have a provider which returns an Animal Object - in my case, an Object
with lots of int codes.

My Dog Object then, must contain both the codes, and the translation of
those codes. Therefor, Dog inherits from Animal and adds the pieces
needed for those code translations.

The problem is in your "therefore". I don't see any reason why Dog
needs to derive from Animal in this case. Why not create a type which
keeps a reference to the Animal that you pass into the constructor, but
without inheriting from Animal?
 
I

Ikke

"Ignacio Machin \( .NET/ C# MVP \)" <ignacio.machin AT dot.state.fl.us>
wrote in
public class Animal
{
protected int numberLegs;
public Animal()
{
numberLegs=4;
}
protected Animal(Animal animal)
{
this.numberLegs = animal.numberLegs;
}
}

public class Dog:Animal
{
public Dog(Animal animal):base(animal)
{

}
}


Will that work for you?

I'm afraid that will not work for me.

You see, the Animal class is pregenerated for me and stuck inside a .dll .

In other words, I am not to alter the Animal class in any way.

Thanks anyway,

Ikke
 
I

Ikke

The problem is in your "therefore". I don't see any reason why Dog
needs to derive from Animal in this case. Why not create a type which
keeps a reference to the Animal that you pass into the constructor,
but without inheriting from Animal?

Thanks for the reply, Jon, but wouldn't that defy the laws of Object
Oriented programming? Surely if a Dog is an Animal, the inheritance link
should be kept.

Another reason would be that one could argue that you are 'hiding' the
animal aspect of Dog inside the Dog class, following your example.

Thanks,

Ikke
 
I

Ikke

That's what I think is called a "object proxy"

http://www.dofactory.com/Patterns/PatternProxy.aspx


public class Dog
private m_animal
public Dog (Animal an )
this.m_animal = an;


public string Name
{get { return this.m_animal.Name ; }}


Try that out. I think its better to keep an internal copy of your
Animal (m_animal) than to .. "map" all the properties over to internal
member variables.

That why , you don't have to really keep tracking of sync'ing
up...because you'll return the property of m_animal.

Thanks for the link and the information - but as I already posted in a
reply to Jon, I don't think this is a good solution in this case.

Ultimately, should there be no other way I'd need to go this route, but it
seems unnatural to me.

Thanks,

Ikke
 
B

Bruce Wood

I can think of two ways to solve this, then, depending upon what Animal
provides and what you need.

The first would be to use aggregation rather than inheritance. Dog
_isn't_ an Animal, but it instead _contains_ an Animal, and exposes all
properties and methods that Animal exposes, simply re-routing them to
the corresponding Animal properties and methods. The downside here is
that you could not use Dog wherever Animal is allowed, in collections,
etc.

The second would work only if Animal has setters for all of its public
properties. Then you could code what Ignacio suggested, but move the
"copy constructor" out of Animal and into Dog:

public Dog : Animal
{
public Dog(Animal a)
{
base.Foo = a.Foo;
base.Bar = a.Bar;
...etc...
}
}

or, if Animal has a complete constructor that takes arguments that map
straight onto its properties:

public Dog : Animal
{
public Dog(Animal a) : base(a.Foo, a.Bar, ... )
{
}
}

Again, it all depends upon what facilities Animal provides for
initialization / setting its internal state. If it provides next to
nothing then you're back to solution #1.
 
J

Jon Skeet [C# MVP]

Ikke said:
Thanks for the reply, Jon, but wouldn't that defy the laws of Object
Oriented programming? Surely if a Dog is an Animal, the inheritance link
should be kept.

It doesn't sound like Dog *is* an Animal. There's nothing in your
description to suggest there's a natural inheritance chain. Maybe there
is and you just haven't described it, of course, but it's definitely
worth considering the possibility of *not* using inheritance. You may
well want to use interfaces, in a sort of proxying model - the original
type could implement an interface, and your type could implement the
same interface, proxying calls to the original object, possibly
modifying passed in parameters or returned values as appropriate.
Another reason would be that one could argue that you are 'hiding' the
animal aspect of Dog inside the Dog class, following your example.

Not really - it's called composition or aggregation, and it's a very
common part of OOP. Again though, the rest of the group doesn't really
know enough about your situation to say for sure. That's the down-side
of using made-up types instead of real ones :(
 
B

Bill Butler

Ikke said:
I have a provider which returns an Animal Object - in my case, an Object
with lots of int codes.

From your description it sounds like you don't directly call Animal's c'tor.
Sounds more like you do something like:
Animal animal = Provider.ProvideAnimal(blah);
as opposed to
Animal animal = new Animal(blah);

If it were the latter case, then yes, inheritance is the way to go
Dog dog = new Dog(foo, bar);
Animal animal = dog; // no problem

But, once again, it sounds like your starting point is a fully instantiated Animal.
You would *like* to do
Dog dog = Provider.ProvideDog(blah);
but instead you need to do
Animal animal = Provider.ProvideAnimal(blah);
Dog dog = new Dog(animal);

*IF* you have access to Animals C'tor you could do this.
*IF* Animal provided a Copy constructor you would be golden

Can you call new Animal(whatever);?
Can you call new Animal(animal)? // copy c'tor

If you don't have access to either, than you are out of luck.
My Dog Object then, must contain both the codes, and the translation of
those codes. Therefor, Dog inherits from Animal and adds the pieces
needed for those code translations.

So I was thinking along the lines of a constructor like the following:
public Dog(Animal animal)
{
// here I copy every property from animal to the new dog Object
}

But this would mean copying a lot of fields, which is cumbersome and
errorprone. Surely there must be a simpler way?

I agree, Yuck.
But, unless you have access to the point where the Animals are being created in the first place, or
unless Animal provides a copy constructor you are in for a slog.(assuming you can access any c'tor
that is)

As Jon suggested earlier, composition may be the cleanest, least error prone solution.

Often times there are multiple appropriate OOP designs.

Bill
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,
Thanks for the reply, Jon, but wouldn't that defy the laws of Object
Oriented programming? Surely if a Dog is an Animal, the inheritance link
should be kept.

Another reason would be that one could argue that you are 'hiding' the
animal aspect of Dog inside the Dog class, following your example.

I agree with Jon , try this instead of using Animal and Dog try using ClassA
and ClassB and see if the relationship is as clear still.
 
I

Ikke

Hi,


I agree with Jon , try this instead of using Animal and Dog try using
ClassA and ClassB and see if the relationship is as clear still.

First of all, I'd like to thank everyone who contributed to this thread.

In the end, after having discussed the offered options with the other
developers, we decided to go with the Object Proxy method described by
Sloan, and it works perfectly.

Thanks again, everybody!

Ikke
 

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