Inheritance 2020
Inheritance is one of the pillars of OOP that facilitates code reuse.
Code reuse comes in two flavors: classical inheritance (the is-a relationship) and the containment/delegation model (the has-a relationship). Here, we'll begin by examining the is-a inheritance model.
When we establish is-a relationships between classes, we are building a dependency between two or more class types. The basic idea behind the classical inheritance is that new classes may extend the functionality of existing classes.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BasicInheritance { class Car { public readonly int maxSpeed; private int curSpeed; public Car(int max) { maxSpeed = max; } public Car() { maxSpeed = 45; } public int Speed { get { return curSpeed; } set { curSpeed += value; if (curSpeed > maxSpeed) { curSpeed = maxSpeed; } } } static void Main(string[] args) { Car c = new Car(70); c.Speed = 50; Console.WriteLine("Speed is {0} mph", c.Speed); Console.ReadLine(); } } }
Output is:
Speed is 50 mph
Note that the Car is using encapsulation services to control access to the private curSpeed field using a public property named Speed.
We want build a new class Van which also support a maximum speed, current speed, and a property named Speed to allow the object user to modify the object's state.
The existing class that will serve as the basic for the new class is a base or parent class. The extending classes are derived or child classes.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BasicInheritance { class Van : Car { } class Car { public readonly int maxSpeed; private int curSpeed; public Car(int max) { maxSpeed = max; } public Car() { maxSpeed = 45; } public int Speed { get { return curSpeed; } set { curSpeed += value; if (curSpeed > maxSpeed) { curSpeed = maxSpeed; } } } static void Main(string[] args) { Van v = new Van(); v.Speed = 10; Console.WriteLine("Van: speed {0} mph", v.Speed); Console.ReadLine(); } } }
Note that although we didn't add any members to the Van class, we have direct access to the public Speed property of parent class, and we could reuse code. However, the encapsulation is preserved. So, the following code results in a compiler error:
static void Main(string[] args) { Van v = new Van(); v.Speed = 10; Console.WriteLine("Van: speed {0} mph", v.Speed); // error because v can't access private members using an object reference! v.curSpeed = 80; Console.ReadLine(); }
If the Van defined its own set of members, it would not be able to access any private member of the Car base class:
class Van : Car { public void vanMethod() { // Fine! Van can access public method of a parent Speed = 35; // Error because Van cannot access private members of parent curSpeed = 25; } }
The .NET platform demands that a given class have exactly one direct base class. It is not possible to create a class type that directly derives from two or more base classes, multiple inheritance. So, the following code is illegal:
class IllegalClass: BaseClassA, BaseClassB {}
Instead, .NET platform does allow a given class type to implement any number of discrete interfaces. In this way, a C# type can exhibit a number of behaviors while avoiding the complexities associated with multiple inheritance.
While a class can have only one direct base class, it is permissible for an interface to directly derive from multiple interfaces. In this way, we can build sophisticated interface hierarchies that model complex behaviors.
The sealed keyword prevents inheritance from occurring. When we mark a class as sealed,, the compiler will not allow us to derive from this type.
For example, if we have decided that it makes no sense to further extend the Van class:
sealed class Van : Car { }
If we attempt to derive from this class, we would receive a compile-time error:
class AnotherVan : Van {}
Sealing a class makes the best sense when we are designing a utility class. For example, the System namespace defines numerous sealed classes. We can verify this for ourselves by opening up the Visual Studio 2010 Object Browser under View menu and selecting the System.String type defined within the mscorlib.dll assembly.
Note that in the picture above, it's using sealed keyword in the Summary window. So, it would be illegal if we attempt to extend System.String:
class MyNewString : String {}
Visual Studio 2010 allows us to establish base/derived class relationships visually at design time. To use this feature of the IDE, we should include a new class diagram file into our current project:
Project -> Add New Item menu options
Once we click the Add button, we'll be presented with a blank designer surface.
To add types to a class designer, simply drag each file from the Solution Explorer window onto the surface. When we do so, the IDE responds by automatically including all types on the designer surface. Also note that if we delete an item from the visual designer, this will not delete the associated source code, but simply take it off the designer surface.
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization