[C#] Inheritance
Author |
Message |
rdrake
|
Posted: Sat Jun 27, 2009 12:09 am Post subject: [C#] Inheritance |
|
|
So, you want to learn more about inheritance in C#? Well, here we go...
Much like Java, in C# there is no multiple inheritance. You can inherit from multiple interfaces but not classes.
Let's start off with a simple class and go from there.
code: | public abstract class Shape
{
public abstract float GetArea();
} |
Our shape class has a simple method, GetArea(), that is supposed to calculate the area of the particular shape. We mark it as abstract because we have no idea how to calculate the area of the specific shape as there is no shape yet! By marking it as abstract we do not need to give the function a body either.
Also note the lack of a constructor. Since we don't have any values to initialize yet, there's no need for a constructor.
So let's add a specific shape. In this case, a triangle.
code: | public class Triangle : Shape
{
public float Base { get; private set; }
public float Height { get; private set; }
public Triangle(float b, float height)
{
this.Base = b;
this.Height = height;
}
} |
Perfect, we created a new Triangle class which inherits from Shape with two properties; base and height. The constructor takes in the values of these properties and sets them. Go ahead and compile the code.
Uh oh, it doesn't compile. Why, you might ask? Remember how we declared the GetArea() method in the Shape class as abstract? Well, the compiler expects any concrete (non-abstract) class to implement this method. Otherwise if somebody called this method it wouldn't know what to do.
So let's implement it.
code: | public class Triangle : Shape
{
public float Base { get; private set; }
public float Height { get; private set; }
public Triangle(float base, float height)
{
this.Base = base;
this.Height = height;
}
public override float GetArea()
{
return this.Base * this.Height / 2;
}
} |
Much better, it now compiles. We now have a simple inheritance structure where we have a Shape class that has a Triangle subclass.
Let's try coming up with a more complicated chain.
code: | public class Rectangle : Shape
{
public float Width { get; private set; }
public float Height { get; private set; }
public Rectangle(float width, float height)
{
this.Width = width;
this.Height = height;
}
public override float GetArea()
{
return this.Width * this.Height;
}
} |
Ok, nothing special about the above class. It's very similar to the Triangle class with a different name for the property and a different formula calculating the area. Now let's subclass Rectangle to give us a Square class.
code: | public class Square : Rectangle
{
public Square(float width)
: base(width, width) { }
} |
Now, you're probably thinking "...that's it?" Well, yes, that's it. Since a square is just a special case of a rectangle where the sides are all equal length (which any child above the age of 3 will tell you), we just call the Rectangle class' constructor with the same dimension twice.
Note the syntax to call the base class' constructor. In Java it would look something like this:
Java: | public class Square extends Rectangle {
public Square (float width ) {
super (width, width );
}
} |
Let's say you wanted to access the methods of a Square object. Try this out:
code: | Rectangle r = new Square(5f);
Console.WriteLine(r.GetArea()); |
...should write out "25." Perfect!
Say you want to have multiple constructors in the same class. How would you do that? Why this way, of course! Let's re-write Rectangle to take advantage of the Size class .NET offers us.
code: | public class Rectangle : Shape
{
public float Width { get; private set; }
public float Height { get; private set; }
public Rectangle(Size s)
: this(s.Width, s.Height) { }
public Rectangle(float width, float height)
{
this.Width = width;
this.Height = height;
}
public override float GetArea()
{
return this.Width * this.Height;
}
} |
Yup, that's it. We can now initialize Rectangle objects using either the Size class or by passing in the width and height as two floats.
I think that should just about do it for simple inheritance. To make sure you're really understanding the above concepts try predicting what each of the following code snippets will do:
Questions
Will these work? Why or why not?
Problem 1:
code: | Shape s = new Square(5f);
Console.WriteLine(s.GetArea()); |
Problem 2:
code: | Shape s = new Square(5f);
Console.WriteLine(s.Height); |
Problem 3:
code: | Shape s = new Shape(); |
Problem 4:
code: | Square s = new Rectangle(5f, 6f); |
Answers
Problem 1:
Works just fine. It should print out an answer of "25" if all went well.
Problem 2:
Have another look at the Shape class. Does it contain a property called "Height"? No, well that's why you got a compilation error.
The reason calling GetArea() worked in problem 1 is because Shape contained a definition for that method. If you really want you can cast your object back to the subclass when calling properties and methods that only exist on a lower level like so:
code: | Shape s = new Square(5f);
Console.WriteLine(((Square)s).Height); |
Problem 3:
Uh oh, compilation error! Mono is not pleased.
Angry Mono wrote: error CS0144: Cannot create an instance of the abstract class or interface `Shape'
Just like it says, the Shape class is marked as abstract. Since it could contain methods that have not yet been implemented, we cannot create objects of that type. Instead we must subclass the abstract class (forcing us to implement the abstract methods if our subclass is not also abstract), and create instances of that.
Problem 4:
Again it will not compile. The code does not compile because Square is a subclass of Rectangle, not the other way around. Square already knows all about Rectangle and what it contains, but Rectangle does not know everything (if anything) that's been added to Square.
You can do this:
code: | Square s = (Square)new Rectangle(5f, 6f);
Console.WriteLine(s.GetArea()); |
That code will compile, but it throws an exception for the same reason that I explained above -- doing the above does not make sense. Ever.
Well, there you have it. A very basic introduction to inheritance in C#. Next up I'll discuss more features such as differences between public/private/protected in terms of instance variables and extension methods.
Edit: Added code as an attachment.
Description: |
|
Download |
Filename: |
C#-Inheritance-Part1.zip |
Filesize: |
1.23 KB |
Downloaded: |
334 Time(s) |
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
wtd
|
Posted: Wed Jul 01, 2009 7:17 pm Post subject: RE:[C#] Inheritance |
|
|
I see a quick mention of interfaces, but no code examples.
|
|
|
|
|
|
sjjoseph
|
Posted: Wed Jan 13, 2010 5:29 am Post subject: Re: [C#] Inheritance |
|
|
Hello rdrake!!
Nice description about inheritance.
Good to see with example. It is helping in understanding.
Thanks for this post.
|
|
|
|
|
|
|
|