developmentor - a developer services company				  
				      C# Tutorial
   Modules

Inheritance


Goals:

  • Practice creating an inheritance hierarchy.
  • Explore how common code can be placed in a base class.
  • Call a base class constructor.
  • Use new in a derived class to replace an inherited method.
  • Use chaining to call a base class method from a derived class method.

Overview

In this lab we will use inheritance to model different assets in an investment application. The main base class will be Asset and we will have two derived classes: Stock and Property. We will also explore a multilevel inheritance hierarchy by deriving Building and Art from the Property class.


part 1- Classes and fields

Here we will setup the inheritance hierarchy for the investment application. We will start off by defining the classes and their fields. Most of the code has been included to reduce the time needed for this basic part of the lab.

steps:

  1. Asset class. Create a class named Asset and give it three private fields: a string for the name, a double for the cost, and an int for the year the asset was purchased.

    class Asset
    {
    	private string name;
    	private double cost;
    	private int    yearPurchased;
    	...
    }
    

  2. Stock class. Create a class named Stock that is derived from Asset. Give it three private fields: a string for the ticker symbol, an int for the number of shares owned, and a double for the price.

    class Stock : Asset
    {
    	private string symbol;
    	private int    shares;
    	private double price;
    	...
    }
    

  3. Property class. Create a class named Property and derive it from Asset. Give it one private field: a double for the assessed value.

    class Property : Asset
    {
    	private double assessment;
    	...
    }
    

  4. Building class. Create a class named Building and derive it from Property. Give it one private field, a string for the address.

    class Building : Property
    {
    	string address;
    	...
    }
    

  5. Art class. Create a class named Art and derive it from Property. Give it two private fields: a string for the name of the artist and an int for the year in which it was created.

    class Art : Property
    {
    	private string artist;
    	private int    yearCreated;
    	...
    }
    


part 2- Construction

Here we will practice with constructors in inheritance hierarchies. Remember that derived classes are responsible for initializing their own fields and those of their base class. Because of this, constructors tends to get more parameters farther down the hierarchy.

steps:

  1. Add a public constructor to each class in the inheritance hierarchy. Each constructor should take one argument for each field that it needs to initialize. For example, the Asset constructor will have three arguments since Asset has three fields. The Property constructor will have four arguments since it needs values for the three fields from Asset and an additional value for its own field. In your implementation of the derived class constructors, call the base class constructor using the :base syntax.

  2. Create a driver class named Invest and add a Main method. Use code such as the following to test your work. You may need to adjust the parameter order to match your implementation.

    class Invest
    {
    	static void Main()
    	{
    		Stock    microsoft  = new Stock   ("Microsoft", 8000, 1994, "MSFT", 200, 56);
    		Building beachHouse = new Building("Beach House", 9000, 1964, 35000, "123 Seashore Ave, Malibu, CA");
    		Art      nighthawks = new Art     ("Nighthawks", 850, 1955, 7500, "Edward Hopper", 1942);
    		...
    	}
    }
    


part 3- Code in base class

Here we will examine how common code can be placed in the base class and then be available to all derived classes. Without inheritance the common code would have to be repeated in every class.

steps:

  1. Add the following AmortizedCost method to the Asset class. There is no code to write here, simply copy the sample into your application.

    class Asset
    {
    	public double AmortizedCost(int currentYear)
    	{
    		return cost / (currentYear - yearPurchased);
    	}
    	...
    }
    

  2. Apply the AmortizedCost method to each of your sample assets. Notice the benefit here: we wrote one method that now works for all types in the inheritance hierarchy.

    class Invest
    {
    	static void Main()
    	{
    		...		
    		Console.WriteLine("Amortized costs per year:");
    		Console.WriteLine("Microsoft stock ${0}", microsoft .AmortizedCost(2002));
    		Console.WriteLine("Beach house     ${0}", beachHouse.AmortizedCost(2002));
    		Console.WriteLine("Nighthawks      ${0}", nighthawks.AmortizedCost(2002));		
    		...
    	}
    }
    


part 4- Hiding inherited member

It can occasionally happen that a method with the same signature appears in both a base class and a derived class. When this happens, the derived class version hides the base class version. Some times this is intentional: the base class does something one way and the derived class wants to do it a bit differently. The designers of C# want to make sure that such hiding does not happen accidentally so they ask that the derived class method be labeled with the keyword new. If the method is not labeled new then a warning is generated by the compiler. This technique forces class designers to acknowledge when they are hiding an inherited method. The theory is that this will lead to more robust code since hiding will not occur accidentally.

steps:

  1. Add a public ComputeValue method to the Asset, Stock, and Property classes. The versions in the derived classes must be labeled with new to avoid a compiler warning. The implementation of the Asset version should return the cost, the Stock version should calculate the value using price and shares, and the Property version should return the assessed value.

    class Asset
    {
    	public double ComputeValue()
    	{
    		...
    	}
    	...
    }
    

  2. Apply the ComputeValue method to each of your sample assets.

    class Invest
    {
    	static void Main()
    	{
    		...		
    		Console.WriteLine("Valuations:");
    		Console.WriteLine("Microsoft stock ${0}", microsoft .ComputeValue());
    		Console.WriteLine("Beach House     ${0}", beachHouse.ComputeValue());
    		Console.WriteLine("Nighthawks      ${0}", nighthawks.ComputeValue());
    		...
    	}
    }
    


part 5- Chaining to base class

A derived class method may want to take advantage of some of the services offered by its base class by calling one of the base class methods. This often occurs between base and derived versions of the same method. The keyword base is used to indicate the base class version should be called in preference to the derived class method of the same name.

steps:

  1. Add a public Print method to each class in the hierarchy. Use base to allow the derived class versions to chain to the base class versions. After the call to the base version finishes, the derived versions can finish the job by printing the values of the fields in the derived class. Remember to use new in the signature of the derived class versions.

    class Asset
    {
    	public void Print()
    	{
    		...
    	}
    	...
    }
    

  2. Apply the Print method to each of your sample assets.

    class Invest
    {
    	static void Main()
    	{
    		...		
    		microsoft .Print();
    		beachHouse.Print();
    		nighthawks.Print();
    		...
    	}
    }
    

Solutions:

This material is excerpted from the Programming C# course offered by DevelopMentor.