c# – Inheritence in Action

Lets say we have a supermarket and it sells a different types of fruits, then you could create a class for each type of fruit:

The above will output:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InheritenceInAction
{
    class Program
    {
        static void Main(string[] args)
        {
			// Here we create an object using the orange class
            Orange AnOrange = new Orange(1.25, 45, "Spain", "25-01-2015", "sweet", true, "clementine");
			string ContainsSeedsSentence;
            if (AnOrange.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }

            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            AnOrange.FruitName, AnOrange.OrangeType, AnOrange.CountryOfOrigin, AnOrange.Price, AnOrange.SweetnessLevel, AnOrange.Calories, AnOrange.UseByDate, ContainsSeedsSentence);

			// Here we create an object using the banana class
            Banana ABanana = new Banana(0.43, 135, "Kenya", "25-05-2014", " very sweet", false, "Cavendish");
        	if (ABanana.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }
            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            ABanana.FruitName, ABanana.BananaType, ABanana.CountryOfOrigin, ABanana.Price, ABanana.SweetnessLevel, ABanana.Calories, ABanana.UseByDate, ContainsSeedsSentence);

        }
    }

    class Orange
    {

		private string fruitname;
        public string FruitName
		{
			get{return fruitname;}
			set{fruitname = "Orange";}
		}
		// notice that we have expanded the Fruitname property above, because we want it to be a constant.
		// All other properties are defined in the standard way below:
        public double Price { get; set; }
        public int Calories { get; set; }
        public string CountryOfOrigin { get; set; }
        public string UseByDate { get; set; }
        public string SweetnessLevel { get; set; }
        public bool ContainsSeeds { get; set; }
        public string OrangeType { get; set; }

        public Orange(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string OrangeType)
        {
			FruitName = FruitName;		// This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.OrangeType = OrangeType;
        }
    }

    class Banana
    {
		private string fruitname;
        public string FruitName
		{
			get{return fruitname;}
			set{fruitname = "Banana";}
		}
		// notice that we have expanded the Fruitname property above, because we want it to be a constant.
		// All other properties are defined in the standard way below:
        public double Price { get; set; }
        public int Calories { get; set; }
        public string CountryOfOrigin { get; set; }
        public string UseByDate { get; set; }
        public string SweetnessLevel { get; set; }
        public bool ContainsSeeds { get; set; }
        public string BananaType { get; set; }

        public Banana(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string BananaType)
        {
			FruitName = FruitName;   // This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.BananaType = BananaType;
        }
    }
}

The resulting output would be:

Now there is a good chance that this supermarket sells a lot of different types of fruits, e.g apples, melons, mangoes, etc.

So what we could do is write a class for each fruit, however if we did this, we would discover that there are a lot of repeating members within each fruit class.

For example in the above 2 classes, orange and banana you will have noticed that these 2 classes had the following member in common:

this.Price = Price;
this.Calories = Calories;
this.CountryOfOrigin = CountryOfOrigin;
this.UseByDate = UseByDate;
this.SweetnessLevel = SweetnessLevel;
this.ContainsSeeds = ContainsSeeds;

The only two properties that were different in each class were:

fruitname (they had different “set” values)
this.BananaType (unique to banana class)
this.OrangeType (unique to orange class)

In this scenario, this presents an ideal scenario to take advantage of the concept of inheritence, to rewrite the code in fewer lines and make it more organised/structured at the same time.

Inheritance is to do with recognising which classes are actually are special versions (aka sub-classes) of more general classes. We do this by looking for classes that are similar (both in what they contain and what they represent) and then group them together.

We can then create a high-level class (aka base class) and move the common members out of the sub-classes and place them into the base-class.

For example orange, and banana both represent the same kind of logical object, which is a “fruit”. Hence we can organise our code by creating a new “fruit” class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InheritenceInAction
{
    class Program
    {
        static void Main(string[] args)
        {
            // Here we create an object using the orange class
            Orange AnOrange = new Orange(1.25, 45, "Spain", "25-01-2015", "sweet", true, "clementine");
            string ContainsSeedsSentence;
            if (AnOrange.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }

            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            AnOrange.FruitName, AnOrange.OrangeType, AnOrange.CountryOfOrigin, AnOrange.Price, AnOrange.SweetnessLevel, AnOrange.Calories, AnOrange.UseByDate, ContainsSeedsSentence);

            // Here we create an object using the banana class
            Banana ABanana = new Banana(0.43, 135, "Kenya", "25-05-2014", " very sweet", false, "Cavendish");
            if (ABanana.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }
            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            ABanana.FruitName, ABanana.BananaType, ABanana.CountryOfOrigin, ABanana.Price, ABanana.SweetnessLevel, ABanana.Calories, ABanana.UseByDate, ContainsSeedsSentence);
            Console.ReadLine();
        }
    }

	// Here we created a new class that is the baseclass (aka the parent class)
	// of the orange and banana class.
    class Fruit {

        public double Price { get; set; }
        public int Calories { get; set; }
        public string CountryOfOrigin { get; set; }
        public string UseByDate { get; set; }
        public string SweetnessLevel { get; set; }
        public bool ContainsSeeds { get; set; }

    }

	// Here we used the ":" notation to indicate that Orange is a child-class of the Fruit.
	// It means that all the members (which at the moment are properties) that are defined in the
	// base class, are also implicitly defined in the child class.
    class Orange : Fruit
    {

        private string fruitname;
        public string FruitName
        {
            get { return fruitname; }
            set { fruitname = "Orange"; }
        }
        // notice that we have expanded the Fruitname property above, because we want it to be a constant.
        // All other properties are defined in the standard way below:

        public string OrangeType { get; set; }

        public Orange(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string OrangeType)
        {
            FruitName = FruitName;		// This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.OrangeType = OrangeType;
        }
    }

	// Here we used the ":" notation to indicate that Orange is a child-class of the Fruit.
	// It means that all the members (which at the moment are properties) that are defined in the
	// base class, are also implicitly defined in the child class.
    class Banana : Fruit
    {
        private string fruitname;
        public string FruitName
        {
            get { return fruitname; }
            set { fruitname = "Banana"; }
        }
        public string BananaType { get; set; }

        public Banana(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string BananaType)
        {
            FruitName = FruitName;   // This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.BananaType = BananaType;
        }
    }
}

This again gives the same output. Note also that the class “fruit” is something we might never to use directly, it is just being used here as way of oraganising/structuring/streamlining our code as well as categorising our classes.

Also, as you can see, the base class essentially “inherits” the members of it’s parent class. That where this term comes from.

Now, a supermarket might sell other things on top of fruits. E.g. meat products, such as beef, chicken, fish,….etc.

In this scenario we can take a similar approach that we did for fruits, and create a parent class called “meat”, and then subclasses for beef, chicken, and etc.

In this scenario, we would end up with 2 parent classes, “fruit” and “meat”. And both of these parent-classes are very likely to have a number of properties in common, e.g. price.

So what we can do is make both the fruit and meat classes themselves sub classes of an even higher level class, e.g a class called “food”, which in turn can be a subclass itself for an even higher level class called “Item”. The item class could cover non-food items e.g. newspapers, washing-up liquid,….etc.

If we just stick to the fruit example for now, we can organize/structure the above code even more by creating the “food” and “item” classes:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InheritenceInAction
{
    class Program
    {
        static void Main(string[] args)
        {
            // Here we create an object using the orange class
            Orange AnOrange = new Orange(1.25, 45, "Spain", "25-01-2015", "sweet", true, "clementine");
            string ContainsSeedsSentence;
            if (AnOrange.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }

            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            AnOrange.FruitName, AnOrange.OrangeType, AnOrange.CountryOfOrigin, AnOrange.Price, AnOrange.SweetnessLevel, AnOrange.Calories, AnOrange.UseByDate, ContainsSeedsSentence);

            // Here we create an object using the banana class
            Banana ABanana = new Banana(0.43, 135, "Kenya", "25-05-2014", " very sweet", false, "Cavendish");
            if (ABanana.ContainsSeeds)
            {
                ContainsSeedsSentence = "This fruit contains seeds.";
            }
            else
            {
                ContainsSeedsSentence = "This fruit is seedless.";
            }
            Console.WriteLine("\n\nThis {0} is a {1} and is grown in {2} and costs  £{3}. It's a {4} fruit and contains {5} calories. It's use-by date is {6}. {7}",
            ABanana.FruitName, ABanana.BananaType, ABanana.CountryOfOrigin, ABanana.Price, ABanana.SweetnessLevel, ABanana.Calories, ABanana.UseByDate, ContainsSeedsSentence);
            Console.ReadLine();
        }
    }

    class Item
    {
        public double Price { get; set; }
        public string CountryOfOrigin { get; set; }
    }

    class Food : Item
    {

        public int Calories { get; set; }

        public string UseByDate { get; set; }

    }

    class Fruit : Food
    {

        public string SweetnessLevel { get; set; }
        public bool ContainsSeeds { get; set; }

    }

    class Orange : Fruit
    {

        private string fruitname;
        public string FruitName
        {
            get { return fruitname; }
            set { fruitname = "Orange"; }
        }
        // notice that we have expanded the Fruitname property above, because we want it to be a constant.
        // All other properties are defined in the standard way below:

        public string OrangeType { get; set; }

        public Orange(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string OrangeType)
        {
            FruitName = FruitName;		// This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.OrangeType = OrangeType;
        }
    }

    class Banana : Fruit
    {
        private string fruitname;
        public string FruitName
        {
            get { return fruitname; }
            set { fruitname = "Banana"; }
        }
        public string BananaType { get; set; }

        public Banana(double Price, int Calories, string CountryOfOrigin, string UseByDate, string SweetnessLevel, bool ContainsSeeds, string BananaType)
        {
            FruitName = FruitName;   // This is inserted to trigger the FruitName property's set element.
            this.Price = Price;
            this.Calories = Calories;
            this.CountryOfOrigin = CountryOfOrigin;
            this.UseByDate = UseByDate;
            this.SweetnessLevel = SweetnessLevel;
            this.ContainsSeeds = ContainsSeeds;
            this.BananaType = BananaType;
        }
    }
}