Object Oriented Programming (C#)

Object Oriented Programming (C#)

There are primarily two methods of programming in use today: procedural and object-oriented. The earliest programming languages were procedural, meaning a program was made of one or more procedures. A procedure is simply a function that performs a specific task such as getting data from users, performing calculations, displaying outputs, and so on.

Procedural programming is centered on creating procedures, whereas object-oriented programming (OOP) is centered on creating objects. An object is a software entity that contains both data and procedures that work on that data.

Here's what we will cover:

  1. Classes and objects

  2. Constructors

  3. OOP Principles: Encapsulation, Inheritance, Polymorphism

  4. Importance of OOP

Classes and Objects

Before an object can be created, it must be designed by a user. The user determines the data attributes and methods that are necessary, then creates a class. A class is a blueprint that defines the attributes and the methods common to all objects of a certain kind. A class definition starts with the keyword class followed by the class name.

class Pet {
}

The class body contains the properties and methods enclosed by curly braces {}. The properties and methods are members of the class.

class Pet {
    // Properties
    string Name;
    string Gender;
    int Age;
    string AnimalType;

    // Method
    public void MakeSound() {
        Console.WriteLine("Grrrr");
    }
}

An object is an instance of a class. Once we've written the class, we can create objects based on that class. Creating an object is called instantiation. Each object has its characteristics. The characteristics of an object are called properties and the values of these properties describe the current state of an object.

For example, a Pet (an object of the class Pet) can be 3 years old, type of dog, and named Scoobie.

class Pet {
    public string Name;
    public int Age;
    public string AnimalType;

     // Other properties, methods, events...
}

class Program {
    static void Main() {
        // Create a new instance of the class Pet
        Pet myPet = new Pet();
        myPet.Name = "Scoobie Doe";
        myPet.Age = 5;
        Console.WriteLine("myPet name is {0}, and age {2}", myPet.Name, myPet.Age);
    }
    /* 
        Output: 
        myPet name is Scoobie, and age 3
    */
}

The code above declares a Pet object named myPet. Notice the dot operator . is used to access members of the class.

Constructors

A class constructor is a special member method of a class that is executed whenever a new object of that class is created. A constructor has exactly the same name as its class, is public, and does not have any return type. A class may have multiple constructors that take different arguments.

Constructors are very useful for assigning an initial value to certain member variables of an object when created, just as shown in the following example:

class Pet {
    public string Name;
    public int Age;
    public string AnimalType;

    // Constructor
    public Pet(string, name, int age, string type) {
        Name = name;
        Age = age;
        AnimalType = type;
    }
     // Other properties, methods, events...
}

class Program {
    static void Main() {
        // Create a new instance of the class Pet
        Pet myPet = new Pet("Scoobie", 3, "Dog");
        Console.WriteLine("myPet is a {0} named {1}, and age {2}", myPet.AnimalType, myPet.Name, myPet.Age);
    }
    /* 
        Output: 
        myPet is a Dog named Scoobie, and age 3
    */
}

OOP Principles:

To understand and use object-oriented programming, it is necessary to know the following principles:

Encapsulation

Part of the meaning of the word encapsulation is the idea of "surrounding" an entity, not just to keep what is inside together, but also to protect it. A class can specify how accessible each of its members is to code outside of the class. Methods and variables that aren't intended to be used from outside of the class or assembly can be hidden to limit the potential for coding errors or malicious exploits.

class Pet {
    public string Name;
    public int Age;
    public string AnimalType;
    private string Owner;

    public Pet(string name, int age, string type, string owner) {
        Name = name;
        Age = age;
        AnimalType = type;
        Owner = owner;
    }
    public string GetOwner() {
        return Owner;
    }
}

class Program {
    static void Main() {
        Pet myPet = new Pet("Scoobie", 3, "Dog", "Superfly");
        Console.WriteLine("Pet Name = {0}, Age = {1}, Owner = {2}", myPet.Name, myPet.Age, myPet.GetOwner());
    /* 
        Output: 
        Pet Name = Scoobie, Age = 3, Owner = Superfly
    */
    }
}

In the example above, a new property Owner was added. The private access modifier makes the member accessible from only within the class and hides them from the outside. We used encapsulation to hide the Owner member, then we provided restricted access to it using public methods. The Owner property can be read through the GetOwner method.

C# supports the following access modifiers: public, protected, internal, protected internal, private, and private protected. As seen in previous examples, the public access modifier makes the member accessible from outside the class and the default accessibility is private.

Inheritance

Inheritance enables you to create new classes that reuse, extend, and modify the behavior defined in other classes. A class that derives from another class, called the base class, automatically contains all the public, protected, and internal members of the base class except its constructors and finalizers.

The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive. If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Example of Inheritance in C#:

class Shape
{
    // Properties
    public int X;
    public int Y;
    public int Height;
    public int Width;

    public void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}
// Derived class of Shape
class Rectangle : Shape { }

class Program
{
    static void Main()
    {
        Rectangle rectangle = new Rectangle();
        rectangle.Draw();
        /* 
         Output:
         Performing base class drawing tasks
        */
    }
}

An instance of the derived class Rectangle inherits the method Draw() from the class Shape.

Polymorphism

Polymorphism allows derived classes to have methods with the same names as methods in their base class. It gives the ability for a program to call the correct method depending on the type of object that is used to call it.

We can create a base class called Shape, and derived classes such as Rectangle, and Circle. Give the Shape class a virtual method called Draw, and override it in each derived class to draw the particular shape that the class represents.

A derived class can override a base class member only if the base class member is declared as virtual or abstract. The derived member must use the override keyword to explicitly indicate that the method is intended to participate in virtual invocation. The following code provides an example:

class Shape {
    // Properties
    public int X;
    public int Y;
    public int Height;
    public int Width;

    public virtual void Draw() {
        Console.WriteLine("Performing base class drawing tasks");
    }
}
// Derived class of Shape
class Rectangle : Shape {
    public override void Draw() {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a Rectangle");
        base.Draw();
    }
}
// Derived class of Shape
class Circle : Shape {
    public override void Draw() {
        // Code to draw a circle...
        Console.WriteLine("Drawing a Circle");
        base.Draw();
    }
}
class Program {
    static void Main() {
        Rectangle rectangle = new Rectangle();
        rectangle.Draw();
        Circle circle = new Circle();
        circle.Draw();
        /* 
        Output:
        Drawing a Rectangle
        Performing base class drawing tasks
        Drawing a Circle
        Performing base class drawing tasks
        */
    }
}

Importance of OOP

  1. Data Hiding: OOP addresses the problem of code and data separation through encapsulation and data hiding. Encapsulation refers to the combining of data and code into a single object. Data hiding refers to an object’s ability to hide its data attributes from code that is outside the object. Only the object’s methods may directly access and make changes to the object’s data attributes.

  2. Object Reusability: In addition to solving the problems of code and data separation, the use of OOP has also been encouraged by the trend of object reusability. An object is not a stand-alone program but is used by programs that need its services.

  3. Effective Problem Solving: Object-oriented programming is ultimately about taking a huge problem and breaking it down into solvable chunks. For each mini-problem, you write a class that does what you require. And then — best of all — you can reuse those classes, which makes it even quicker to solve the next problem.

You've come to the end of this article, thank you so much for reading thus far, do check out my reference resources.


Reference resources: Microsoft Learn Classes and objects, Object-Oriented Programming, Starting Out with Python Book by Tony Gaddis, Sololearn C# intermediate