As you may have guessed, in order to use inheritance, you must first have a class that provides the fundamental definition or behavior you need. There is nothing magical about such a class. It could appear exactly like any of the classes we have used so far. Here is an example:
class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); return 0; } } This would produce: Circle Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Press any key to continue The above class is used to process a circle. It can request or provide a radius. It can also calculate the circumference and the area of a circle. Now, suppose you want to create a class for a sphere. You could start from scratch as we have done so far. On the other hand, since a sphere is primarily a 3-dimensional circle, and if you have a class for a circle already, you can simply create your sphere class that uses the already implemented behavior of a circle class. Creating a class that is based on another class is also referred to as deriving a class from another. The first class serves as parent or base. The class that is based on another class is also referred to as child or derived. To create a class based on another, you use the following formula: class NewChild : BaseClass { // Body of the new class } In this formula, you start with the class keyword followed by a name from your class. On the right side of the name of your class, you must type the : operator, followed by the name of the class that will serve as parent. Of course, the BaseClass class must have been defined; that is, the compiler must be able to find its definition. Based on the above formula, you can create a sphere class from the earlier mentioned Circle class as follows: class Sphere : Circle { // The class is ready } After deriving a class, it becomes available and you can use it just as you would any other class. Using a variable of the derived class, you can access the public members of the parent class, using the period operator. Here are examples: using System; class Circle { private double _radius; public double Radius { get { if( _radius < 0 ) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } class Sphere : Circle { } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var ball = new Sphere(); ball.Radius = 25.55; Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", ball.Radius); Console.WriteLine("Diameter: {0}", ball.Diameter); Console.WriteLine("Circumference: {0}", ball.Circumference); Console.WriteLine("Area: {0}", ball.Area); return 0; } } This would produce: Circle Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Sphere Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Press any key to continue When a class is based on another class, all public members of the parent class are made available to the derived class. While other methods and classes can also use the public members of a class, the difference is that the derived class can call the public members of the parent class as if they belonged to the derived class. That is, the child class doesn't have to "qualify" the public members of the parent class when these public members are used in the body of the derived class. This is illustrated in the following program: using System; class Circle { private double _radius; public double Radius { get { if( _radius < 0 ) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } public void ShowCharacteristics() { Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", Radius); Console.WriteLine("Diameter: {0}", Diameter); Console.WriteLine("Circumference: {0}", Circumference); Console.WriteLine("Area: {0}", Area); } } class Sphere : Circle { public void ShowCharacteristics() { // Because Sphere is based on Circle, you can access // any public member(s) of Circle without qualifying it(them) Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", Radius); Console.WriteLine("Diameter: {0}", Diameter); Console.WriteLine("Circumference: {0}", Circumference); Console.WriteLine("Area: {0}\n", Area); } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; round.ShowCharacteristics(); var ball = new Sphere(); ball.Radius = 25.55; ball.ShowCharacteristics(); return 0; } } You can also use the this object in the derived class to access the public members of the parent class: using System; class Circle { . . . No Change } class Sphere : Circle { public void ShowCharacteristics() { // Because Sphere is based on Circle, you can access // any public member(s) of Circle without qualifying it(them) Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", this.Radius); Console.WriteLine("Diameter: {0}", this.Diameter); Console.WriteLine("Circumference: {0}", this.Circumference); Console.WriteLine("Area: {0}\n", this.Area); } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; round.ShowCharacteristics(); var ball = new Sphere(); ball.Radius = 25.55; ball.ShowCharacteristics(); return 0; } } When you use this, all members of the derived class and the public members of the parent would be available.
You can notice in the above example that the derived class produces the same results as the base class. In reality, inheritance is used to solve various Object-Oriented Programming (OOP) problems. One of them consists of customizing, adapting, or improving the behavior of a feature (property or method, etc) of the parent class. For example, although both the circle and the sphere have an area, their areas are not the same. A circle is a flat surface but a sphere is a volume, which makes its area very much higher. Since they use different formulas for their respective area, you should implement a new version of the area in the sphere. Based on this, when deriving your class from another class, you should be aware of the properties and methods of the base class so that, if you know that the parent class has a certain behavior or a characteristic that is not conform to the new derived class, you can do something about that. A new version of the area in the sphere can be calculated as follows: using System; class Circle { private double _radius; public double Radius { get { if( _radius < 0 ) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } class Sphere : Circle { public double Area { get { return 4 * Radius * Radius * Math.PI; } } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var ball = new Sphere(); ball.Radius = 25.55; Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", ball.Radius); Console.WriteLine("Diameter: {0}", ball.Diameter); Console.WriteLine("Circumference: {0}", ball.Circumference); Console.WriteLine("Area: {0}", ball.Area); return 0; } } This would produce: Circle Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Sphere Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 8203.3512239 Press any key to continue Notice that, this time, the areas of both figures are not the same even though their radii are similar. Besides customizing member variables and methods of a parent class, you can add new members as you wish. This is another valuable feature of inheritance. In our example, while a circle is a flat shape, a sphere has a volume. In this case, you may need to calculate the volume of a sphere as a new method or property of the derived class. Here is an example: using System; class Circle { private double _radius; public double Radius { get { if (_radius < 0) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } class Sphere : Circle { public double Area { get { return 4 * Radius * Radius * Math.PI; } } public double Volume { get { return 4 * Math.PI * Radius * Radius * Radius / 3; } } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var ball = new Sphere(); ball.Radius = 25.55; Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", ball.Radius); Console.WriteLine("Diameter: {0}", ball.Diameter); Console.WriteLine("Circumference: {0}", ball.Circumference); Console.WriteLine("Area: {0}", ball.Area); Console.WriteLine("Volume: {0}\n", ball.Volume); return 0; } } This would produce: Circle Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Sphere Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 8203.3512239 Volume: 209595.623770645 Press any key to continue
Imagine you create a property or method in a derived class but that property or method already exists in the parent class. Consider the following Cone class: using System; public class Circle { private double _radius; public double Radius { get { if (_radius < 0) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } public class Cone : Circle { private double _height; public double Height { get { return _height; } set { if (_height <= 0) _height = 0; else _height = value; } } } When you access the property or method in the derived class, you must make sure you indicate what member you are accessing. To make this possible, you can use the base keyword. To access a property or method of a parent class from the derived class, type the base keyword, followed by the period operator, followed by the name of the property or method of the base class. Here is an example: using System; public class Circle { . . . No Change } public class Cone : Circle { private double _height; public double Height { get { return _height; } set { if (_height <= 0) _height = 0; else _height = value; } } public double Volume { get { return Math.PI * base.Radius * base.Radius * this.Height / 3; } } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var birthdayHat = new Cone(); birthdayHat.Radius = 25.55; Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", birthdayHat.Radius); Console.WriteLine("Diameter: {0}", birthdayHat.Diameter); Console.WriteLine("Circumference: {0}", birthdayHat.Circumference); Console.WriteLine("Area: {0}", birthdayHat.Area); Console.WriteLine("Volume: {0}\n", birthdayHat.Volume); return 0; } } This would produce: Circle Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Sphere Characteristics Side: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Volume: 0 Press any key to continue . . . Notice that the volume of the cylinder is 0 because the height was not initialized. Sometimes when using a derived class, you may want to access the constructor of the parent class. Normally, in most languages, including C# and its parent C++, you can't just call a constructor as if it were any method. Because there is a special relationship between a derived class and its parent, you can call the parent from the child. Of course, calling any public method of the parent class is easy: you simply use its name. To call a constructor of the parent class from the derived class, you must use a constructor of the derived class. To do this, when defining the constructor of the derived class, after the parentheses, type : base followed by parentheses. If you are calling a constructor that doesn't take any argument, leave the parentheses empty. Here is an example: using System; public class Circle { private double _radius; public Circle() { this._radius = 0.00d; } } public class Cone : Circle { private double _height; public Cone() : base() { this._height = 0.00D; } } If you are calling a constructor that takes one argument, in the parentheses of base, you can enther a constant value. Here is an example: public class Circle { private double _radius; public Circle() { this._radius = 0.00d; } public Circle(double rad) { this._radius = rad; } } public class Cone : Circle { private double _height; public Cone() :base() { this._height = 0.00D; } public Cone(double hgt) : base(28.00d) { this._height = hgt; } } Most of the time, you will want to initialize a member (a field) of the parent class, in which case you would not know the value of that member before run-time. In this case, the constructor in the child class should have an argument that corresponds to an argument of a constructor of the base class. That argument of the child class is the one you should pass to base. Here is an example: using System; public class Circle { private double _radius; public Circle() { this._radius = 0.00d; } public Circle(double rad) { this._radius = rad; } public double Radius { get { if (_radius < 0) return 0.00; else return _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } public class Cone : Circle { private double _height; public Cone() : base() { this._height = 0.00D; } public Cone(double rad, double hgt) : base(rad) { this._height = hgt; } public double Height { get { return _height; } set { if (_height <= 0) _height = 0; else _height = value; } } public double Volume { get { return Math.PI * base.Radius * base.Radius * this.Height / 3; } } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = -25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var birthdayHat = new Cone(-42.64, 20.18); Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", birthdayHat.Radius); Console.WriteLine("Height: {0}", birthdayHat.Height); Console.WriteLine("Diameter: {0}", birthdayHat.Diameter); Console.WriteLine("Circumference: {0}", birthdayHat.Circumference); Console.WriteLine("Area: {0}", birthdayHat.Area); Console.WriteLine("Volume: {0}\n", birthdayHat.Volume); return 0; } } This code means that you are asking the parent constructor to handle the value, that is, to initialize it. This could would produce: Circle Characteristics Radius: 25.55 Diameter: 51.1 Circumference: 160.535249 Area: 2050.837805975 Sphere Characteristics Radius: 0 Height: 20.18 Diameter: 0 Circumference: 0 Area: 0 Volume: 0 Press any key to continue . . . Notice that all values of the area and the volume of the cone are 0. This is because the parent class that was asked through its constructor to validate the height is equipped with code to reject negative value. The child class was not given that ability. This is a good feature of inheritance where a parent can perform an assignment for the child. Imagine you create a class used to process a circle as we saw earlier. You can use this as the base class for a sphere. Both the circle and the sphere have an area but their values are different. This means that, as mentioned in our introduction to inheritance, when deriving the sphere class, you would have to calculate a new area for the cube. If you create or declare a new member in a derived class and that member has the same name as a member of the base class, when creating the new member, you may want to indicate to the compiler that, instead of overriding that same method that was defined in the base class, you want to create a brand new and independent version of that method. When doing this, you would be asking the compiler to hide the member of the base class that has the same name, when the member of the current class is invoked. To do this, type the new keyword to its left. Here is an example: using System; class Circle { private double _radius; public double Radius { get { return (_radius < 0) ? 0.00 : _radius; } set { _radius = value; } } public double Diameter { get { return Radius * 2; } } public double Circumference { get { return Diameter * Math.PI; } } public double Area { get { return Radius * Radius * Math.PI; } } } class Sphere : Circle { new public double Area { get { return 4 * Radius * Radius * Math.PI; } } public double Volume { get { return 4 * Math.PI * Radius * Radius * Radius / 3; } } } class Exercise { public static int Main() { var round = new Circle(); round.Radius = 25.55; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Side: {0}", round.Radius); Console.WriteLine("Diameter: {0}", round.Diameter); Console.WriteLine("Circumference: {0}", round.Circumference); Console.WriteLine("Area: {0}", round.Area); var ball = new Sphere(); ball.Radius = 25.55; Console.WriteLine("\nSphere Characteristics"); Console.WriteLine("Side: {0}", ball.Radius); Console.WriteLine("Diameter: {0}", ball.Diameter); Console.WriteLine("Circumference: {0}", ball.Circumference); Console.WriteLine("Area: {0}", ball.Area); Console.WriteLine("Volume: {0}\n", ball.Volume); return 0; } }
|