Introduction to Object Oriented Programming for Beginners

An overview of the concept of Object Oriented Programming, a key concept in software design, with examples of classes and inheritance.

3,239 words, estimated reading time 12 minutes.
Introduction to Programming with C#

This article is part of a series of articles. Please use the links below to navigate between the articles.

  1. Learn to Program in C# - Full Introduction to Programming Course
  2. Introdution to Programming - C# Programming Fundamentals
  3. Introduction to Object Oriented Programming for Beginners
  4. Introduction to C# Object-Oriented Programming Part 2
  5. Application Flow Control and Control Structures in C#
  6. Guide to C# Data Types, Variables and Object Casting
  7. C# Collection Types (Array,List,Dictionary,HashTable and More)
  8. C# Operators: Arithmetic, Comparison, Logical and more
  9. Using Entity Framework & ADO.Net Data in C# 7
  10. What is LINQ? The .NET Language Integrated Query
  11. Error and Exception Handling in C#
  12. Advanced C# Programming Topics
  13. All About Reflection in C# To Read Metadata and Find Assemblies
  14. What Are ASP.Net WebForms
  15. Introduction to ASP.Net MVC Web Applications and C#
  16. Windows Application Development Using .Net and Windows Forms
  17. Assemblies and the Global Assembly Cache in C#
  18. Working with Resources Files, Culture & Regions in .Net
  19. The Ultimate Guide to Regular Expressions: Everything You Need to Know
  20. Introduction to XML and XmlDocument with C#
  21. Complete Guide to File Handling in C# - Reading and Writing Files

The object-oriented approach to programming tries to represent abstract or concrete things of the real world in a type of computer code called classes. This article is designed to give you an overview of the concept of Object Oriented Programming, classes, inheritance and abstraction.

What is Object Oriented Programming?

Object Oriented Programming is a branch of computer programming which is centred around objects rather than actions, and data rather than logic. Objects are modelled after things in the real world or creating data models. By modelling data and things, a set of related properties and actions can be created and interacted with.

Object Oriented Programming takes the view that the objects we want to manipulate are more important than the logic required to manipulate them.

What is a Class in Object Oriented Programming?

A class can be thought of as a blueprint for a noun, e.g. a person, place or thing. Nouns have attributes that describe them such as Size, Mass, Temperature, Speed and so on. These attributes are called fields.

A noun can also have actions or processes associated with it. For example, a car could have an action of Accelerate, which would affect the attribute of Speed. These actions are called methods.

A class cannot be used by itself, but it is used to instantiate (create) an instance of an object, which shares all the same fields and methods. Because it is a blueprint, you can create many, many instances, all with the same fields and methods. An instance of a class is called an object. One thing you must keep in mind is that each object that is created from a class is unique; each instance of a class will have its own values for the fields, totally separate from the values of the other objects.

This concept of creating one class that can be reused many times is the foundation of Object Oriented Programming and effective code reuse.

A class should be as specific to the task as possible and only contain nouns dedicated to the task for which the class is to perform.

Why use Classes?

Now, let's have a look at where object-oriented programming really comes into its own. There is a concept known as inheritance where one class can inherit all the methods and fields of a parent, or base, class and also add new functionality, or replace existing methods. This allows a new class to be more focused, targeted towards the object being modelled.

To put that into English with the car example, every car manufacturer uses the same base class. This class defines a basic car with four wheels, a steering wheel, brakes, headlights, seats etc... However, if every manufacturer only used this blueprint, every car produced would be exactly the same - what would be the point?

What we can do is take the functionality from the base class and create another car class and add functionality to it. We can add central locking, water temperature and paint. A different manufacturer may use trim colour and oil temperature and ABS brakes. We can override the methods from the base class so that the basic seats are now heated leather seats, the headlights are HID.

Classes can also use other classes. Our base car class can use a base engine class. Our new car class can override this base engine class to use a super turbo-charged jet-powered engine if we wish.

Classes in C#

A C# application is in essence a collection of classes, structures (shortened to struct) and types.

Firstly, classes and structs are essentially the same, apart from two key differences.

  • Classes are a reference type, structs are value types
  • Classes can use inheritance whereas structs cannot.

Defining a Class

A class is introduced using the class keyword, followed by the name of the class you are creating. Because a class is a block of code, it requires the use of curly brackets (braces).

Let's use the example above and create a Car class. I've called the class called baseCarClass because we will be using this class as a base for new classes in future tutorials.

In the example, we identified several fields and methods associated with a car class.

We are going to create a sample application using the baseCarClass, so create a new console project, and copy the following code into the window.

C#
class baseCarClass
{
}

We can now add in variable declarations for some of the properties of the base car, for example, paint colour, number of seats and direction.

The .Net Framework, nor the compiler are affected by the order in which you declare fields or methods; however, it greatly improves readability if you declare properties at the start of a class, followed by its methods.

C#
class baseCarClass
{
  public string Colour { get; set; }
  public int numberOfSeats { get; set; }
  public int direction { get; set; }
  public string modelName { get; set; }
}

So far all we have done is create a blueprint for a class. We shall now see how to create an actual car object.

A class is a user-defined type so we use the same syntax as declaring an int (for example), but a class also needs initialising with the new keyword. This will instantiate an instance of the class on the heap.

In the Main method of the console application, create an instance of the baseCarClass like this:

C#
static void Main()
{
  baseCarClass myCar = new baseCarClass();
}

We can now set the various attributes of the car.

In your Main method, create an instance of the baseCarClass:

C#
static void Main()
{
  baseCarClass myCar = new baseCarClass();
  myCar.Colour = "blue";
  myCar.numberOfSeats = 4;
  myCar.modelName = "Demo Car MKI";
}

Using the class as a blueprint means that we can create multiple cars with different values for each of the properties.

C#
static void Main()
{
  baseCarClass myCar = new baseCarClass();
  myCar.Colour = "blue";
  myCar.numberOfSeats = 4;
  myCar.modelName = "Demo Car MKI";

  baseCarClass myNewCar = new baseCarClass();
  myNewCar.Colour = "yellow";
  myNewCar.numberOfSeats = 2;
  myNewCar.modelName = "Sports Car MKI";
}

Class Methods

We have just created a class with a few properties. We can add a few methods to our classes which will contain certain logic.

C#
class baseCarClass
{
  public bool isEngineRunning { get; set; }
  public decimal speed { get; set; }
  public decimal distanceTraveled { get; set; }
  public decimal fuelLevel { get; set; }
  public Color colour { get; set; }

  public void startEngine()
  {
  }
  
  void accelerate()
  {
  }
  
  void brake()
  {
  }
  
  void stopEngine()
  {
  }
}

The compiler is not affected by the order in which you declare fields or methods; however, it greatly improves readability if you declare fields and properties at the start of a class, followed by its methods.

Classes as a Data Type

At this stage, our car does not have an engine, so it's pretty useless. There are many different types of engines that a car can have and we are going to model a base engine as we have created a base car. This way our cars can have a variety of engines.

C#
class baseEngineClass
{
  public string name { get; set; }
  public int numberOfCylinders { get; set; }
  public int MPG { get; set; }
  public int acceleration { get; set; }
}

We can add one class to another in the same way as we add an integer or string. A class is simply another data type.

Let's add the engine to our car class.

C#
class baseCarClass
{
  public string Colour { get; set; }
  public int numberOfSeats { get; set; }
  public int direction { get; set; }
  public string modelName { get; set; }
  public baseEngineClass engine { get; set; }
}

Now all that is left to do is create an engine and give it to a car.

C#
static void Main()
{
  baseCarClass myCar = new baseCarClass();
  myCar.Colour = "blue";
  myCar.numberOfSeats = 4;
  myCar.modelName = "Demo Car MKI";

  myCar.engine = new baseEngineClass();
  myCar.engine.name = "Slow Engine"
  myCar.engine.numberOfCylinders  = 4;
  myCar.engine.MPG = 50;
  myCar.engine.acceleration = 2;
}

C# Class Inheritance

Class inheritance is one of the key principles in object-oriented programming. It allows one class to pass on properties and methods to child classes so that they can reuse, extend, and modify existing functionality.

In simplistic terms, class inheritance allows one class to inherit methods, properties and fields from a parent class and to also build upon its functionality. Classes inherit from another class using a colon followed by the class name to inherit from on the class declaration line.

let's create a sports car class which has a folding roof.

C#
public class SportsCar : baseCarClass
{
}

This basic class definition should be familiar, with the additional inheritance " : baseCarClass" bit added on. This is saying that we want a new class called SportsCar which contains everything that baseCarClass contains.

Next, we can add the folding roof as a boolean property, with two methods, one to raise the roof and the other to lower it.

C#
public class SportsCar : baseCarClass
{
  private bool isRoofUp;

  public void RaiseRoof()
  {
    isRoofUp = true;
  }

  public void DropRoof()
  {
    isRoofUp = false;
  }
}
C#
SportsCar myCar = new SportsCar();

The SportsCar contains all the properties of the baseCarClass plus those we defined in the SportsCar class.

Using C# Properties

We saw in this example that we created some properties with a get and set keyword after them. These are called properties.

Properties are the same as fields, however, they can execute code when you access them via getters and setters. This allows for the protection of class information and the enforcement of business rules.

As a general rule, if you mark a field as public, you should convert it to a property. This is because a lot of actions, such as serialisation and deserialisation (we'll cover these later on) only work for properties.

A property can be defined in two ways - there is the automatic property we just saw which is a shorthand version where the compiler automatically generated the backing variable and getter and setter code.

There is also the expanded version which allows you to add logic and security to the get or set methods. Maybe only certain users can update the value while everyone can read it.

C#
private int _month

public int Month
{
  get 
  {
    return _month;
  }

  set
  {
    if ((value >= 1) &amp;&amp; (value <= 12))  
    {
      _month = value;
    }
  }
}

This will ensure that the value of _month will always be between 1 and 12. If the user of your class passes a value outside this range it will not be applied.

C# Class Constructors and Destructors

Class constructors and destructors are methods that are automatically called when a class is instantiated or destroyed. They are provided so that the class can be initialized with the correct data, open connections and so on and also to finalise and close connections and files before the object is removed from memory.

You do not need to provide a constructor method in your classes as the compiler will automatically initialize fields to default values using a default constructor which takes no parameters. A constructor should be used when you need non-default values to be initialized. Constructors can also be overloaded to extend the functionality of the method. If you do create an overloaded constructor, the compiler will not provide a default, so if you still require a constructor with no parameters you must provide it yourself.

A constructor is declared as a public method with the same name as the class, in this example public baseCarClass() is the constructor.

C#
class baseCarClass
{
    public bool isEngineRunning;
    public decimal speed;
    public decimal distanceTraveled;
    public decimal fuelLevel;
    public Color colour;

    / Constructor
    public baseCarClass()
    {
    }

    public void startEngine()
    {
    }

    void accelerate()
    {
    }

    void brake()
    {
    }

    void stopEngine()
    {
    }
}

When you compile your class, the compiler will automatically add a default "hidden" constructor for you, however, if you want to provide additional functionality then you must do this yourself. When instantiating the class with the new keyword you can pass a parameter to the constructor.

C#
/ Constructor
public baseCarClass(Color carColour)
{
    colour = carColor;
}
C#
baseCarClass car = new baseCarClass(Color.Yellow);
/car.colour == Color.Yellow

baseCarClass car = new baseCarClass(); / Will not compile

As soon as you code a constructor, the compiler will not automatically provide one for you. Only those coded will be present, so if you create a constructor with a parameter you will not be able to create an object with a parameterless constructor unless you write one.

This example constructor will only allow a baseCarClass to be created when a colour is given. The default with no parameters is not available. If you do need it, you will have to create it yourself.

C#
/ Default Constructor
public baseCarClass()
{
    / Call the most specific constructor to prevent duplicate code
    baseCarClass(Color.Black);
}

/ Custom Constructor
public baseCarClass(Color carColour)
{
    colour = carColour;
}
C#
baseCarClass car = new baseCarClass(Color.Yellow);
/car.colour == Color.Yellow

baseCarClass car = new baseCarClass(); / Now will compile
/car.colour == Color.Black - default colour

Constructors and Inheritance

By default, all inherited classes will use the constructor as the base class, unless overridden.

Because the constructor was added to the baseCarClass, any class inheriting from it can also benefit from having the constructor, thus:

C#
SportsCar sporty = new SportsCar(Color.Pink);
/sporty.colour == Color.Pink

To create a constructor specifically for the SportsCar class we define it in the same way:

C#
/ Constructor
public SportsCar(bool roofUp)
{
    isRoofUp = roofUp;
}
C#
SportsCarcar = new SportsCar(true);
/car.isRoofUp == true

What colour is the SportsCar?

Because we have not provided colour in our constructor, the default constructor for the base class has been called making the colour of the car Color.Black. You can call the constructor of the base class and give it a parameter. This can be done in one of two ways.

Firstly, to provide a default "static" value:

C#
public SportsCar(bool roofUp):base(Color.PeachPuff)
{
    isRoofUp = roofUp;
}

Or you can add another parameter to the constructor and use this to call the base constructor.

C#
public SportsCar(bool roofUp, Color carColour): base(carColour)
{
    isRoofUp = roofUp;
}

Private Constructors

You can also mark the constructor as private, which will have the effect of not allowing the class to be instantiated. This is useful for abstract classes where you should not create an instance.

C#
class PoliceCar
{
  private PoliceCar()
  {
  }
}

The following code will not compile as the program cannot "see" the private method.

C#
PoliceCarcar = new PoliceCar();

Destructors

Destructors work slightly differently in that the syntax is a shortcut to an override of the Finalize method, however, all you need to know is that they are used to finalise the class ready for removal from memory. The Garbage Collector always calls the destructor; you never call it from within your code. Since you cannot call the destructor, you cannot overload the destructor method.

C#
~baseCarClass ()
{
  / Code to scrap the car (realistically this would be closing files and connections)
}

Method Overloading and Overriding in C#

When inheriting from another class, you may wish to change the default behaviour of a method or create a different method signature. You can do this by overloading the method with your own code.

Method signatures are formed from the parameter list, in particular, the data types. Methods can share the same name within the class as long as the signature is different.

C#
static int Add(int a, int b)
{
  return a + b;
}

In the above example, the signature should be (int, int). In the Visual Studio code editor, if you were to call the Add method after you enter the '(' IntelliSense will pop up the available parameters. Notice that there is only one option given to you.

Method Overloading

We can add an overloaded method with a different signature and IntelliSense will now present two options, one for each signature of the overloaded method. The compiler finds two methods of the same name and two calls to that method with different parameters. It can tell the difference by comparing the signatures of the methods.

C#
static int Add(int a, int b, int c)
{
  return a + b + c;
}

The names of the parameter and the return type do not affect the method signature, thus the method below will raise an error because a method already exists for Add(int, int), even though it returns a decimal.

C#
static decimal Add(int a, int b, int c)
{
  return a + b + c;
}

Methods should be overloaded when you have similar methods that require different parameters or you want to add new functionality to existing code, however, you should not use overloading too often as it causes headaches during debugging and testing and is more effort to maintain.

Optional Parameters in C#

C# does not have an implementation of optional parameters like those found in PHP, however, you can simulate this feature using method overloading.

C#
static int Add(int a, int b)
{
  return Add(a, b, 0, 0);
}

static int Add(int a, int b, int c)
{
  return Add(a, b, c, 0);
}

static int Add(int a, int b, int c, int d)
{
  return (a + b + c + d);
}

In this example we can call Add with 2, 3 or 4 parameters and only one functional method is called - the others just pass the data around. You can use IntelliSense to see the different overloads and their parameters.

Overloading Example
Overloading Example

Full Code

C#
using System;
using System.Drawing;

class TestBaseCarClass
{
    static void Main()
    {
        Console.WriteLine(Add(1, 1));
    }

    static int Add(int a, int b)
    {
        return Add(a, b, 0, 0);
    }

    static int Add(int a, int b, int c)
    {
        return Add(a, b, c, 0);
    }

    static int Add(int a, int b, int c, int d)
    {
        return a + b + c + d;
    }
}

This code is only shown as an example. If you really want to create a function that accepts any number of parameters of the same type, then the params keyword is better suited.

Method Overriding

Methods can be overridden, replacing the default behaviour or extending it. In this example we will override the ToString() method for the ArrayList class so that it may return something more meaningful.

C#
using System;
using System.Collections.Generic;

class Program
{
  static void Main()
  {
     ArrayList myList = new ArrayList();

    myList.Add("Hello");
    myList.Add("World");
    myList.Add("123456");

    Console.WriteLine(myList.ToString());
  }
}

You may expect the ToString to return "Hello World 123456", but it returns "System.Collections.ArrayList", which isn't particularly helpful.

We can override this default behaviour by creating a new class, which inherits from the ArrayList. We can then override the ToString method by using the override keyword.

C#
class myArrayList : System.Collections.ArrayList
{
    public override string ToString()
    {
        return base.ToString();
    }
}

The base keyword is used to refer to the object. By default, the override method will return base.ToString(). You can use this base object to call the non-overwritten method. We are going to amend the code to suit our needs, and in this example, we are going to convert the array list to show the contents of the list, one item per line.

C#
using System;
using System.Text;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        myArrayList myList = new myArrayList();

        myList.Add("Hello");
        myList.Add("World");
        myList.Add("123456");

        Console.WriteLine(myList.ToString());
    }
}

class myArrayList : System.Collections.ArrayList
{
    public override string ToString()
    {
        StringBuilder result = new StringBuilder();
        string[] theItems = (string[])base.ToArray(typeof(string));

        foreach (string item in theItems)
        {
            result.AppendLine(item);
        }
        return result.ToString();
    }
}

Now when we create an instance of our new class and call the ToString method we are given "Hello World 123456" one item per line.

Object Oriented Programming Summary and Conclusions

In this rather lengthy article, we have looked at what Object Oriented Programming is, learned what a class is, what properties are, how to inherit classes, constructors and destructors, overloading and overriding. In Part 2 we will look at some more object-orientated examples and a few more concepts.

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 11 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. MI

    On Wednesday 29th of June 2011, Mini said

    Good One.Finally i understood whats operator overloading is.

  2. G

    On Tuesday 17th of May 2011, g said

    gud article

  3. AN

    On Tuesday 15th of February 2011, Anonymouse said

    Good article!!! Very simple explanation in that even a novice developer will get the hang of the concept easily.

  4. HI

    On Tuesday 4th of January 2011, Hil Jacla III said

    Thank you!
    its a good way to manipulate custom types in the most straightforward way. Good Job...^^

  5. NM

    On Wednesday 22nd of December 2010, Nirvin M said

    Wow! This is website is awesome. I bookmarked this page and regularly learning .NET from this site. I congratulate the team...Thank you for wonderful tutorials...

  6. KU

    On Sunday 1st of August 2010, Kunal said

    Hi Friends,

    Can anybody please tell how to return more than 1 value from a function (means suppose I pass two int to a function and get three result SUM, MULT, DIV of that values using single function)

    1. SC

      On Wednesday 29th of September 2010, Scott replied

      Hi Kunal,

      hopefully you received a timely response to this earlier... but you could use an object (or possibly struct) as your return type. just create a class with meaningful return members and then extract them from the object after the method call.

      You could also potentially use a combination of return value and out variables to accomplish the same thing without a return object.

      hope this helps.

      Regards,
      Scott

  7. KU

    On Sunday 1st of August 2010, Kunal said

    Hi Friends,

    Can anybody please tell how to return more than 1 value from a function (means suppose I pass two int to a function and get three result SUM, MULT, DIV of that values using single function).

  8. PA

    On Thursday 31st of December 2009, Priya Arora said

    can u plz help to find out the difference between abstraction & encapsulation. We know that encapsulation is hiding the unnecessary data & abstraction is showing the necessary data but wats the difference in this both are performing the same task.

  9. FI

    On Friday 19th of June 2009, Finally... said

    Finally a good explanation of operator overloading - thank you!

  10. SA

    On Sunday 15th of February 2009, sanay said

    Hi
    I found a good example for my method we can pass the aray values inside the method with the help of "param" thanx a lot

    sanjay Vishwakarma