Link to home
Start Free TrialLog in
Avatar of paulwhelan
paulwhelan

asked on

Inheritence Example?

Hi

Could someone help me flesh out this inheritence example - explaining virtual, override and anything else Id need to know along rhe way.

Im a c# and oop newbie!

Thanks
Paul

----------Human.cs----------------

class Human : Mammal
    {
        //constructor
        public Human()
            : base()
        {          
        }

        new public void setNumberOfLegs(int nol)
        {
            numberOfLegs = nol;
        }

        private int numberOfLegs;

    }





-----------------Mammal.cs-----------------

class Mammal
    {
        //constructor
        public Mammal()
        {
            numberOfLegs = 0;
        }

        public void setNumberOfLegs(int nol)
        {
            numberOfLegs = nol;
        }

        private int numberOfLegs;
    }
Avatar of apresto
apresto
Flag of Italy image

virtual:

If you use the word virtual for a method in a base class it means that it can be overriden by another class that inherits it.

i.e

in Mammal if you have

public virtual getNumOfLegs(int Nol)
{
}

you can create a method called getNumOfLegs in a clas inheriting from this class like so:

public override getNumOfLegs(int Nol)
{
}

We'll cover abit at a time so we dont overload you :o)
ASKER CERTIFIED SOLUTION
Avatar of Carl Tawn
Carl Tawn
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You should also be aware of overloading constructors with inheritance:

using the example above, lets say you wanted to set the value of numberOfLegs on instantiation of Human you could overload the constructor of the base and the Human class like so:
      
in mammal:
      
        public Mammal()
        {
            numberOfLegs = 0;
        }
            
        public Mammal(int nol)
        {
            numberOfLegs = nol;
        }
            
in Human
      
        public Human(): base()
        {          
        }      

        public Human(int Nol): base(Nol)
        {
                  numberOfLegs = Nol;
        }
            
now when you call Human(2) you also set the value of numberOfLegs in the base class
Now on to variable scoping:

   class Mammal
   {
       private int numOfLegs;          // Only available to this class
       protected int numOfWings;    // Only available to this class and any derived classes
       public int age;                      // Available to any class
   }

   class Human : Mammal
   {
        public Human()
        {
              numOfLegs = 4;          // Illegal because private in base class
              numOfWings = 2;        // Valid because we derive from Mammal
              age = 10;                   // Valid because public in base
        }
   }
Avatar of PoeticAudio
PoeticAudio

Inheritance is a very handy tool indeed! First lets figure out what virtual and override mean.

virtual means that you can override =) Well, a little more then that actually. Virtual means you can have implementation in the base class and "override" that implementation in a derrived class. Lets do a different example...

Lets assume that all animals make a noise. Dogs bark, cats meow, wives scream... but they are all animals of some sort.

Lets start with the Animal class (we could make this abstract and such (which we should in this case) but I don't want to confuse you with that... yet =)

public class Animal
{
    public Animal()
    {}

    public virtual void Speak()
    {
        MessageBox.Show("I spoke!");
    }
}


Okay, here we have a basic animal with a basic speak method. It is maked as virtual because in classes that derrive from this we want to have custom implementation. We can create an animal right now and just have it speak like so

Animal animal = new Animal();
animal.Speak();

Now lets say we need a dog. Well, we want the dog to be an animal, but we want it to bark instead. So we will make the Dog class

public class Dog : Animal  //derrive from Animal
{
    public Dog()
    {}

    public override void Speak() //override the speak method so this animal barks instead
    {
        MessageBox.Show("Bark!");
    }
}

Now we can do:

Animal animal = new Dog(); //because a dog is an animal
animal.Speak();   //it barks now!

pretty sweet eh? Since the method in the base class (Animal) is virtual, we can also call the base method from the Dog class, so it will show
"I spoke" and then "Bark!" We do this like so: (we're still in the dog class, we're just changing the Speak method

public override void Speak() //override the speak method so this animal barks instead
{
    base.Speak();  // we call the base implementation here, and then the animal barks. We can also put this after the MessageBox
                          //so that it barks first.
    MessageBox.Show("Bark!");
}


Okay. The above example is all fine and dandy, but why would we have the base animal speak at all? We don't know what it is, so why would we have "I spoke!"... that sounds like a human to me! so instead we will make animal abstract. Since we are making it abstract we can create a direct instance of it, but we have a sort if "interface" for all other animals to use.

public abstract class Animal
{
    public Animal()
    {}

    public abstract void Speak();  //now it's abstract, we don't have any implementation, we let the derrived classes handle that.
}

now for the dog class

public class Dog : Animal
{
    public Dog()
    {}

    public override void Speak()  //we still override, but we can't call base because there is no implementation
    {
         MessageBox.Show("Bark!");
     }
}

we can still do
Animal animal = new Dog();
animal.Speak();

plus we can create as many animals as we want, as long as they derrive from Animal we can do a lot of cool stuff (which I can't go into right now cuz i'm at work)


I hope this shed some light!

sorry this line
 Since we are making it abstract we can create a direct instance of

should be
Since we are making it abstract we CANT create a direct instance of

for example, since animal is abstract we CAN NOT do Animal animal = new Animal();
Avatar of paulwhelan

ASKER

Thanks guys.

Some questions.

1)

This line -

Mammal Bob = new Human();

has me confused ;)

I thought the syntax should always be

Classname Objectname = new Classname();

Does

Mammal Bob = new Human();

make sense?
If so what is it doing?

And can I do
Human Bob = new Mammal();

And is it the same as
Mammal Bob = new Mammal();
or
Human Bob = new Human();





2)

If I do

Human Bob = new Human();

I create a human object. And say I set
numberOfLegs = 2;
why would I want to assign
numberOfLegs = 2;
within the Mammal object?

Thanks!
Paul
Think of inheritance as an "is-a" relationship.

Human inherits from Mammal, so Human is a Human, but is also a Mammal. Therefore:

Mammal Bob = new Human();     // Valid because Human is-a Mammal - due to its inheritance

This is an advantage because if you had more than one class that derives from mammal you could create them both as Mammal. That might be a bit confusing, so take a look at this sample:

class Mammal
{
    virtual void Speak()
    {
        MessageBox.Show("Mammal speaks");
    }
}

class Human : Mammal
{
    override void Speak()
    {
        MessageBox.Show("Human speaks");
    }
}

class Ape : Mammal
{
    override void Speak()
    {
        MessageBox.Show("Ape speaks");
    }
}


This declares two classes that derive from Mammal. Now consider this short sample that demonstrates passing objects to a funtion:

static void Main()
{
        Mammal[] arr = new Mammal[] { new Human(), new Ape() };
        foreach (Mammal m in arr)
        {
            m.Speak();
            SpeakToMe(m);
        }
}

static void SpeakToMe(Mammal m)
{
    m.Speak();
}

So, beacuse both Human and Ape derive from Mammal we can add them both to an array of Mammals, and we can also pass them to a method that takes a Mammal as a parameter.
Thanks Carl,

The 'is-a' helps a lot.
So if I create a
Mammal Paul = new Human();
He's firstly a human above all and then also a Mammal.

One thing - within my Human class (after I'd created the Mammal class and stated Human inherits from it)
I did this

public override void setLifeExpectancy(int le)
        {
            //compiler generated - why?
            //base.setLifeExpectancy(le);
            lifeExpectancy = le;
        }

(I have a field 'private int lifeExpectancy')

Any idea why the compiler generated that code?
And if I call the base method does that set both the base and derived 'lifeExpectancy'?

Thanks very much for the help!
Paul
1) Yes, Paul is a Human, but is also a Mammal due to inheritance. However, because you have created Paul on a variable of type Mammal, on the methods defined in the Mammal class are available. But any overrides will be called in the derived version. I'll clarify that with an example if it doesn't make sense.

2) Do you have a virtual setLifeExpectancy() in you Mammal class ? If you don't you will get an error because there is nothing to override. What error are you getting ?

3)

   lifeExpectancy = le;

Will only set the value in the class it is declared in. If you have a public or protected version in the base then you can set it with:

    base.lifeExpectancy = le;
Sorry another question.
About abstract.

In Mammal I changed the method to be abstract

//public virtual string saySomething()
//{
//    return "I'm a Mammal";
//}
//make this an abstract!
public abstract string saySomething();

Then in my form I do -

Mammal myMammal = new Mammal();
textBox1.Text = myMammal.saySomething();

I figured this wouldn't make sense - just wanted to see what would happen.

So now it underlines
saySomething
in
public abstract string saySomething();

'InheritanceExample.Mammal.saySomething()' is abstract but it is contained in nonabstract class 'InheritanceExample.Mammal'

Do I have to make the class abstract?

Thanks
Paul
Yes, if any of the methods are abstract then the class must also be declared abstract. However the class can be abstract without any of its members being abstract.
Thanks Carl,

Is it possible to have abstract and nonabstract methods in the base class?

For example

public abstract string saySomething(); //fine as a 'Mammal' shouldn't say something
and
public virtual void makeHeartBeat()
{
heartBeatCounter = heartBeatCounter + 1;
//records the number of heartbeats
}

i.e. a Mammal can't say something but a Mammal (and all inheriting Mammals) can have a heart beat.

Surely the whole point of 'abstract' is that you're quantifying that the class cannot have that method but 'non-abstract' methods are allowed?

Does that make sense =)
Thanks
Paul
Yes, you can have non-abstract methods. The difference is that abstract methods HAVE to be implemented by derived classes, non-abstract do not, but can be if they are virtual.
So whats the difference between a virtual and an abstract?

An abstract is not implemented in the base class but must be implemented in deriving classes?
And a virtual can (or must?) be implemented in the base class and can be overridden in deriving classes?

I think I'm getting it ;)
Cheers
Paul
Thats right. Abstract must be implemented, virtual CAN be but doesn't have to be.
Sorry just one last thing

Whats the difference between

Mammal Bob = new Human();

and

Human Bob = new Human();

Will the later be able to use the base class Mammal?

Thanks
Paul
Mammal Bob = new Human() : You will only be able to call methods declared in Mammal from this. However, any method in Human() that overrides a virtual method in Mammal will be called.

Human Bob = new Human() : You will be able to call all public methods of both Mammal and Human.
Essentially "Human Bob = new Human()" can call all method because it is both a Mammal and a Human.

Whereas with "Mammal Bob = new Human()", the variable is a Mammal, therefore it doesn't know about any methods defined for a Human.
Sorry I'm at it again =)

I'm trying to create a class that will derive from Bird.

Now the first thing that came to mind was Flightless and CanFly.

But are they merely fields within Bird?
How would I know what would be a deriving class?
(tough question I know)

And within Mammal - Human : Would I have further classes Male and Female? Or would I define this in a field in Human?

Increasing points.

Thanks
Paul
It all depends on the circumstances and how much detail you need. This is where the inital analysis/design comes in.

Flightless and CanFly sound like they would be properties of a bird. But whether you set them directly or they are set based on something else depends on how they need to be used.

Same with Male/Female, are the two very different in terms of how they function in the context of your app, or do you just need to know which is which without it affecting the behaviour.

Be careful with inheritance. Its a very powerful tool, but can be overused, you really need to think about what is important in you classes and how they will be used.
Thanks very much Carl.

Ill finish it after this one!

Within my form I do this

  Mammal Paul = new Human(88);

which calls this constructor in Human : Mammal

  public Human(int le)
        {
            lifeExpectancy = le;
        }

now it doesn't even go to the '{' when I use the debugger and step through line by line.

It immediately hops to the Mammal constructor

//default constructor
        public Mammal()
        {
            lifeExpectancy = 50;
        }


So it sets lifeExpectancy to 50 and not 88 - not good for me ;)
Any ideas why its doing this?

Thanks
Paul

Did you keep going with the debugger ?

Because Human derives from Mammal, everytime you create a Human a Mammal is created as well and its constructor is called first. The Human constructor should then be called after it.
Actually I think I got it

I changed the (nondefault) constructor in Human : Mammal to be

//public Human(int le)
        below - update it in the base too!
        public Human(int le): base(le)
        {
            lifeExpectancy = le;
        }

Although now it seems to call the constructor in Human AND Mammal.
Is that right?

Thanks
Paul
Yes. When you create a Human you also create a Mammal. The base classes constructor is called first.