#567 – Wider vs. Narrower Types

In a object-oriented programming language like C#, due to inheritance, we often end up with a hierarchy of types.

Types lower down in the diagram above are known as derived classes and the class above them, which they inherit from, is known as their base class.  For example, Working is a derived class with respect to Dog, which is its base class.  Notice that a class can be both a derived class and a base class for another class.  (E.g. Working serves as a base class for Boxer).

We also refer to types higher up in the class hierarchy as wider and types further down as narrower.  The Dog class is wider than the Terrier class in the sense that there are more dogs than there are Terriers.  You can also think of the narrower classes as being more specialized–Terrier is a specific type of Dog.

#444 – Interfaces Can Inherit from Other Interfaces

An interface can inherit from other interfaces.  A class implementing an interface must then implement all members of all interfaces in the inheritance chain.

For example, assume that we have an INameAndMotto interface with Name and Motto properties.

    interface INameAndMotto
    {
        string Name { get; set; }
        string Motto { get; set; }
    }

Now we can inherit this interface when we define the IMoo interface.

    interface IMoo : INameAndMotto
    {
        void Moo();
        List<string> MooLog { get; set; }
    }

Now if we specify that the Cow class inherits from IMoo, it must implement all methods in both IMoo and INameAndMotto.

    public class Cow : IMoo
    {
        public string Name { get; set; }
        public string Motto { get; set; }

        public void Moo()
        {
            Console.WriteLine("Moo");
        }

        public List<string> MooLog { get; set; }
    }


#343 – Use the new Keyword to Replace a Method in a Base Class

A derived class inherits data and behavior from its parent class.

There are times when you might want to replace a method in a base class with a new method in the derived class, having the same name.  You can do this using the new keyword.

Assume a Dog class has a Bark method:

    public class Dog
    {
        public void Bark()
        {
            Console.WriteLine("Generic dog {0} says Woof", Name);
        }

You can provide a new version of this method in a class that derives from Dog, using the new keyword.  This new method hides the method in the base class.

    public class Terrier : Dog
    {
        public new void Bark()
        {
            Console.WriteLine("Terrier {0} is barking", Name);
        }

Dog objects will now invoke Dog.Bark and Terrier objects will invoke Terrier.Bark.

            Dog kirby = new Dog("Kirby", 15);
            kirby.Bark();

            Terrier jack = new Terrier("Jack", 17);
            jack.Bark();

#334 – A Base Class Variable Can Refer to Instances of Derived Classes

A variable whose type is a particular class can refer to instances of that class or it can refer to instances of any derived classes.

Assume that we have a Dog class (base class) and a Terrier class (derived class) that inherits from Dog.  A variable of type Dog can then refer to either a Dog or a Terrier.

Dog kirby = new Dog("Kirby", 15);

// Dog variable can point to Terrier
Dog jack = new Terrier("Jack", 17, "Surly");

// Terrier variable can also point to Terrier
Terrier bubba = new Terrier("Bubba", 2, "Happy");

Notice that even though the variable jack is of type Dog, it still points to an instance of a Terrier.

#333 – Class Inheritance Leads to a Hierarchy of Classes

Defining a new class, you can specify that it inherits data and behavior from any other existing class, or you can allow the new class to implicitly inherit from System.Object.  Because the new class can inherit from a class that itself inherits from another class, you end up defining a hierarchy of parent / child (base class / derived class) relationships.

Consider the picture shown below.  The user has defined a Dog class, which implicitly inherits from the predefined System.Object class.  They also define the Hound and Terrier classes, both of which inherit from Dog, as well as the FoxTerrier class, which inherits from Terrier.

A class inherits data and methods not only from its immediate parent, but also from other classes higher up in the inheritance chain.  For example, the FoxTerrier class inherits data and methods from Terrier, but also from the Dog class, as well as the System.Object class.

#332 – Every Class Inherits from Exactly One Class

Every class that you define in C# will inherit from exactly one class.

You can explicitly define a base class that the new class inherits from.

    public class Terrier : Dog

Or you can avoid specifying a base class when you define a new class.

    public class Terrier

If you don’t specify a base class, the new class will be automatically derived from System.Object.  You can see this by causing Intellisense to pop up for an instance of the class.  You see the class members of System.Object–e.g. Equals, GetHashCode, GetType, etc.

#330 – Derived Classes Do Not Inherit Constructors

A derived class inherits all of the members of a base class except for its constructors.

You must define a constructor in a derived class unless the base class has defined a default (parameterless) constructor.  If you don’t define a constructor in the derived class, the default constructor in the base class is called implicitly.

When you define a constructor in a derived class, you can call a constructor in the base class by using the base keyword.

Here’s an example:

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }

    public class Terrier : Dog
    {
        public string Attitude { get; set; }

        // Call the Name/Age constructor in the base class
        public Terrier(string name, int age, string attitude)
            : base(name, age)
        {
            Attitude = attitude;
        }
    }

#329 – A Class Can Inherit Data and Behavior from Another Class

A class can inherit data and behavior from another class.  The new class (“derived class”) automatically includes all members of the class that it inherits from (“base class”) and can also define new members.

To inherit from another class, add a ‘:’ (colon) and the name of the base class in the definition of the derived class.

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void Bark()
        {
            Console.WriteLine("{0} says woof", Name);
        }
    }

    public class Terrier : Dog
    {
        public string Attitude { get; set; }

        public void Growl()
        {
            Console.WriteLine("{0} says Grrrr", Name);
        }
    }

We can now create instances of both the Dog and the Terrier classes:

            Dog lassie = new Dog();
            lassie.Name = "Lassie";
            lassie.Age = 71;
            lassie.Bark();

            Terrier jack = new Terrier();
            jack.Name = "Jack";
            jack.Age = 17;
            jack.Attitude = "Aloof";
            jack.Bark();
            jack.Growl();

#229 – The Core Principles of Object-Oriented Programming

As an object-oriented language, C# supports the three core principles of object-oriented programming:

  • Encapsulation – Hide implementation details in a class from users of the class, exposing only a public interface
  • Inheritance – Derive a subclass from a parent class, inheriting data and behavior from the parent, in an “is-a” relationship.  Inheritance defines a hierarchy of classes.  All classes ultimately inherit from System.Object.
  • Polymorphism – Any subtype may be used where a parent type (or type higher up in the class hierarchy) is expected.  Conversely, a variable of a particular class will be treated as the appropriate subclass.
Follow

Get every new post delivered to your Inbox.

Join 43 other followers