Click here to Skip to main content
15,881,757 members
Articles / Programming Languages / C#
Article

Three Ways To Extend A Class

Rate me:
Please Sign up or sign in to vote.
4.30/5 (30 votes)
4 Apr 2008CPOL3 min read 272K   565   26   8
An article shows three different easy ways to add features on an existing class.

Introduction

There are many times in a developer's career where there comes along a situation where functionality needs to be added to a class. Sometimes one can change the source code of the original class and sometimes not. This article shows three different easy ways to add functionality to an existing class that works in a situation where the developer is not allowed to change the original class. I think this is useful information for beginning C# programmers.

Background

The reasons for a software developer not being able to change the original source code can be numerous. For example, the source class is part of a commercial package that you do not have the source code for. Or there can be a licensing issue that prohibits a developer from changing the code. Whatever the reason for this hindrance is, it's clear that techniques like adding the methods to the original class or making it eat an interface are not possible options. So a developer needs to do something else.

Luckily, Object Oriented Programming methodology gives us two ways: Containment and Inheritance. It's an age old adage that any software engineering problem can be solved by adding a layer of abstraction — this is — in essence, what Containment does. Inheritance works a bit differently, giving development a possibility of inheriting the "knowledge" of the original class and add new functionality. Additionally, C# 3.0 gives yet another option called Extension Methods.

To summarize, here are the three ways of functional class extension when applying changes to original class is not possible:

  • Containment (OOP concept)
  • Inheritance (OOP concept)
  • Extension Methods (C# 3.0 concept)

Let's see how they operate...

Using the Code

In this example, we use a Car class as the original class to which we wish to add functionality. It already has the functionality for accelarating and now we want to add the functionality fo breaking. It's quite an important feature in a car, isn't it?

The attached code sample is a console project in a Visual Studio 2008 solution. The application logic basically just creates a Car object and extends upon it with the above mentioned techniques. It accelerates and brakes that Car objets(s) and shows trace information (status of Velocity property) on the screen.

Here is Car class in UML:

Car.png

(The diagram does not show properties or contructor).

Here is the Car class in code:

C#
public class Car  
    {
        public string Name { get; set; }
        public int Velocity { get; set; }

        public Car(string name)
        {
            this.Name = name;
            Console.WriteLine("\nCreated a {0}", name);
            Console.WriteLine("Velocity is {0}", this.Velocity);
        }

        public void Accelerate()
        {
            this.Velocity++;
            Console.WriteLine("Accelerated {0} to velocity {1}",
                this.Name, this.Velocity);
        }
    }

So, the Car class contains two properties, a constructor and an method for acceleration.

Car class is used like this:

C#
Car c = new Car("Mazda");
c.Accelerate();
// c.Break(); // Can't do this, because this Car does not know how to brake!

As indicated in the comment, this Car object don't know how to break.

It's important to note that in the following examples, the original Car class stays untouched!

Let's add braking functionality, or a Break() method, with containment:

Containment.png

CarContainer class in code:

C#
public class CarContainer
    {
        public Car car;

        public CarContainer(Car c)
        {
            this.car = c;
            Console.WriteLine("\nCreated container for {0}", this.car.Name);
        }

        public void Brake()
        {
            this.car.Velocity--;
            Console.WriteLine("Braked {0} to velocity {1} (with containment)",
                this.car.Name, this.car.Velocity);
        }
    }

CarContainer class is used like this:

C#
// Let's create a container object which has the Break() method and
// feed it the original car object.
CarContainer c1 = new CarContainer(c);
c1.car.Accelerate();
c1.Brake(); // this car knows how to break.

Next, let's add braking functionality with inheritance:

Inheritance.png

ChildCar class in code:

C#
public class ChildCar : Car
    {
        public ChildCar(string name)
            : base(name)
        {
        }

        public void Brake()
        {
            this.Velocity--;
            Console.WriteLine("Braked {0} to velocity {1} (with child class)",
                this.Name, this.Velocity);
        }
    }

ChildCar class is used like this:

C#
// Let's create a child object that inerits Car's ability to accelerate
// and adds functionality to break.
ChildCar c2 = new ChildCar("Volvo");
c2.Accelerate();
c2.Brake(); // This car knows how to break too.

Next, let's add braking functionality with new C# 3.0 feature called Extension Method:

ExtensionMethod.png

I have to admit that I'm not actually sure how to visualize an extension method, so please be kind to me if the above diagram does not comply to UML standards.

CarExtender class in code:

C#
public static class CarExtender
    {
        public static void BrakeForHeavensSake(this Car c)
        {
            c.Velocity--;
            Console.WriteLine("Braked {0} to velocity {1} (with extension method)",
                c.Name, c.Velocity);
        }
    }

CarExtender class is used like this:

C#
// Let's create a third car, this is a normal car.
// There has been defined an extension method to a Car object in the namespace,
// so the BreakForHeavensSake() method is "glued" to this object.
Car c3 = new Car("Mercedes-Benz");
c3.Accelerate();
c3.BrakeForHeavensSake(); // Works ok!

Points of Interest

I've found in my work that using Extension Methods is easy (and fun) way to extend classes. Hope you liked this beginner level article. Feedback is welcome!

History

Version 1.0 submitted on 4.4.2008.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
.Net Developer from Finland

Comments and Discussions

 
QuestionThank you Pin
sara19828-Feb-23 8:11
sara19828-Feb-23 8:11 
GeneralLINQ to SQL Pin
nanyor6-Sep-15 3:16
nanyor6-Sep-15 3:16 
GeneralMy vote of 1 Pin
adekvaten20-Sep-13 5:27
adekvaten20-Sep-13 5:27 
GeneralRe: My vote of 1 Pin
gggustafson28-Feb-14 9:37
mvagggustafson28-Feb-14 9:37 
GeneralMy vote of 4 Pin
_Vitor Garcia_25-Feb-13 23:21
_Vitor Garcia_25-Feb-13 23:21 
GeneralMy vote of 4 Pin
LiamD4-Aug-10 20:47
LiamD4-Aug-10 20:47 
GeneralImportant note... Pin
James Curran22-Apr-08 7:33
James Curran22-Apr-08 7:33 
GeneralGood for begineers Pin
Rajesh Naik Ponda Goa4-Apr-08 22:28
Rajesh Naik Ponda Goa4-Apr-08 22:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.