Beginner Inheritance Question

M

^MisterJingo^

Hi all,

I have a question regarding inheritance. I'll use the following code
for an example (its been stripped down to the minimum):

// code start
using System;

class Animal
{
public string name;

public Animal(string pName)
{
name = pName;
}
}

class Dog : Animal
{
public string noise;

public Dog(string pName, string pNoise) : base(pName)
{
noise = pNoise;
}
}

class Cat : Animal
{
public Cat(string pName) : base(pName) { }
}

class MainApp
{
public static void Main()
{
Animal[] myPets = new Animal[3];

Cat animal1 = new Cat("Bob");
Cat animal2 = new Cat("Billy");
Dog animal3 = new Dog("Rover", "bark");

myPets[0] = animal1 as Animal;
myPets[1] = animal2 as Animal;
myPets[2] = animal3 as Animal;

for (int i = 0; i < 3; i++)
{
if (myPets is Cat)
{
Console.WriteLine("Cat: {0}: ",myPets.name);
}
else if(myPets is Dog)
{
Dog temp;
Console.WriteLine("Dog: {0}: ", myPets.name);

temp = (Dog)myPets;
Console.WriteLine(temp.noise);
}
}
}
}

// code finish

So I create an array of base class to store derived types in, but the
'Dog' type has an extra var which I want to access later.
The way I did it above was to recast a type to Dog (which has
previously been Dog but cast to Animal for storage in the array) from
Animal.

My question is, is there a better way to go about this? I'm guessing
(and learning) at the moment so don't know what good practice is.
Another possible solution is to have 'noise' in the base class, but
this makes the inheritence pointless.

Any help would be appreciated,

Chris
 
J

Jeff Louie

Chris... I think that you are looking for polymorphism as a solution. In
the base
class define a _virtual_ method Voice() and override this method in Cat
and Dog.
Through the magic of polymorphism, the proper method will be called at
runtime, even if you store an array of references (variables) of type
Animal which
refer to instances of class Cat or instances of a class Dog.

Regards,
Jeff
 
M

^MisterJingo^

Jeff said:
Chris... I think that you are looking for polymorphism as a solution. In
the base
class define a _virtual_ method Voice() and override this method in Cat
and Dog.
Through the magic of polymorphism, the proper method will be called at
runtime, even if you store an array of references (variables) of type
Animal which
refer to instances of class Cat or instances of a class Dog.

Regards,
Jeff

Hi Jeff,

I considered including such a method in Animal (base) - but I was
curious if there was a way to call a method of a derived class when it
was stored in an array of base class type.
Is it best to just declare every method used in derived classes in the
base class as virtual? I wasn't sure if this diminished inheritence in
any way (or bloat base class tremendously) - what I mean by this is
that a derived class might have new features, and to place those
features in an earlier class as a virtual type sort of removes the
reason for the inheritence doesn't it?
The example I posted above was an exercise in a book i'm working
through.
 
M

^MisterJingo^

^MisterJingo^ said:
Hi Jeff,

I considered including such a method in Animal (base) - but I was
curious if there was a way to call a method of a derived class when it
was stored in an array of base class type.
Is it best to just declare every method used in derived classes in the
base class as virtual? I wasn't sure if this diminished inheritence in
any way (or bloat base class tremendously) - what I mean by this is
that a derived class might have new features, and to place those
features in an earlier class as a virtual type sort of removes the
reason for the inheritence doesn't it?
The example I posted above was an exercise in a book i'm working
through.

To clarify what I mean. I can understand if 2 derived classes share
functionality, and so that will be best placed as a virtual base class
method, but what if 1 of the derived classes contains unique methods,
which the other derived class doesn't. And you wish to store these
derived classes in an array and call the extra functionality (where
needed).
By storing in an array of base class, the new methods in one of the
derived classes will be inaccessible. Storing these methods as virtual
in base will solve this, but all the other classes (and those derived
from them) will contain methods which will never be used.
I hope this makes more sense.
So is there a way to call these functions (as the code in the first
post seems to do - but I think poorly) or should all possible methods
of future derivied types be blased as virtual in base?
 
J

Joanna Carter [TeamB]

"^MisterJingo^" <[email protected]> a écrit dans le message de (e-mail address removed)...

| To clarify what I mean. I can understand if 2 derived classes share
| functionality, and so that will be best placed as a virtual base class
| method, but what if 1 of the derived classes contains unique methods,
| which the other derived class doesn't. And you wish to store these
| derived classes in an array and call the extra functionality (where
| needed).
| By storing in an array of base class, the new methods in one of the
| derived classes will be inaccessible. Storing these methods as virtual
| in base will solve this, but all the other classes (and those derived
| from them) will contain methods which will never be used.
| I hope this makes more sense.
| So is there a way to call these functions (as the code in the first
| post seems to do - but I think poorly) or should all possible methods
| of future derivied types be blased as virtual in base?

You certainly would *not* include methods unique to some derived classes in
the base class. In fact, designing a class hierarchy from the top level down
is a very poor way to do things. You should always design your classes, in
the first palce, without any inheritance in mind; and then you will start to
see commonality which can logically be extracted out into a base class.

You should also investigate the use of interfaces and/or composition to
accomodate differences in "derived" classes.

Interfaces allow you to specify common behaviour that can cut across
inheritance hierarchies :

e.g.

interface IMakesNoise
{
void MakeNoise();
}

class Cat : Animal, IMakesNoise
{
...
}

class Car : Vehicle, IMakesNoise
{
...
}

This then allows you to have a list of IMakesNoise which have no common
inheritance and still treat them all the same.

But, whether you you straight-forward inheritance or composition to extend
classes, if you need to have differing methods in some subclasses, then
there is no other way than to test each object in a list whilst iterating
it.

However, you can simplfy your example by using polymorphism; i.e. marking
methods/properties as virtual/override :

e.g.

class Animal
{
private string name;


public Animal(string name)
{
this.name = name;
}

public virtual string Name
{
get { return name; }
set { name = value; }
}
}

class Dog : Animal
{
private string noise;

public Dog(string name, string noise) : base(name)
{
this.noise = noise;
}

public string Noise
{
get { return noise; }
set { noise = value; }
}
}

class Cat : Animal
{
public Cat(string name) : base(name) { }

public override string Name
{
get { return "Cat" + name; }
set { base.Name = value; }
}
}

Then your array code can change like this

Animal[] myPets = new Animal[3];

myPets[0] = new Cat("Bob");
myPets[1] = new Cat("Billy");
myPets[2] = new Dog("Rover", "bark");

for (int i = 0; i < 3; i++)
{
Console.WriteLine(myPets.Name);

if (myPets is Dog)
Console.WriteLine(((Dog) myPets).Noise);
}

Joanna
 
C

clintonG

FYI -- WROX publishes a "C# Class Design Handbook" which I'm finding
insightful.

<%= Clinton Gallagher
 
M

^MisterJingo^

Thanks, i'll check it out. I'm currently working through the 'teach
yourself the c# language in 21 days' from sams, and 'windows forms
programming with c#'. If there any other books I should be looking
into, it would be great if anyone could suggest some (perhaps for
intermediate-advanced rather than beginner-intermediate).
 
J

Jeff Louie

MJ.... Inline
I considered including such a method in Animal (base) - but I was
curious if there was a way to call a method of a derived class when it
was stored in an array of base class type.<

Sure. The key concept is that references (variables) have type and
objects
have class. So the reference of type base class still refers to an
object of class
Subclass. You can simply cast the reference to a valid type and invoke
the
visible methods in that type.

http://www.geocities.com/Jeff_Louie/OOP/oop6.htm
Is it best to just declare every method used in derived classes in the
base class as virtual? I wasn't sure if this diminished inheritence in
any way (or bloat base class tremendously) - what I mean by this is
that a derived class might have new features, and to place those
features in an earlier class as a virtual type sort of removes the
reason for the inheritence doesn't it?<

It is not wise to declare every method as virtual since this allows the
extender
of your class to make the base class method completely invisible. Unless
a
class is designed to be extended prefer private fields and non virtual
methods
and sealed classes. If you are designing a class to be extended then it
is wise
to look for instances where you can abstract behavior. Clearly you are
trying
to design a class that can be extended and Voice is a natural if not
classic
example of a polymorphic behavior. Voice is _not_ a good example of a
subclass specific behavior. A better example would be IRetriever which
would
involve responding to hand and whistle signals and retrieving. virtual
methods and polymorphic behavior is one of four common uses of
inheritance.

So let me be clear that an interface in C# represents an abstract IS_A
relationship similar to a pure virtual class in C++ and that C# supports
single
inheritance of implementation and multiple inheritance of interfaces.

Regards,
Jeff
 

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