Object oriented programming (OOP) is a programming structure where programs are organized around objects. The four pillars of Object oriented programming are as described below:
- Encapsulation is when a group of related methods, properties, and other members are treated as a single object.
- Abstraction is the process by which a developer hides everything other than the relevant data about an object to simplify and increase efficiency.
- Inheritance is the ability to receive (“inherit”) methods and properties from an existing class.
- Polymorphism is when each class implements the same methods in varying ways, but you can still have several classes that can be utilized interchangeably.
The above definitions might help you out with interviews, but unless you get a clear picture on each of these concepts, it’ll just remain a definition which we have learned.
Abstraction & Encapsulation
I’ll put in a scenario to understand these two concepts better.
Scenario : Create a form where the customer enters CustomerCode and CustomerName and saves the details
So, looking at the requirement above, we’ll think – What do I need?
I need a customer class which has a customer name, a customer code and an add function which will save the customer name and the customer code to the database
Here I have just answered the ‘what’ part of the scenario, what does my customer class need so that anybody can use this class.
Next, I need to look at the ‘how’ part of the scenario. How am I going to save the customer details, how am I going to validate the customer details, etc.
So, for that I go into a more granular level. I create a validate method which validates the input fields. Also, I’ll have a ‘CreateDBObjects’ method which will create the DB objects, create the connection string, etc.
Now our customer class is complete. So now let’s use this customer class in our application.
So first we need to reference our customer class in the new project. Then create a new object of the customer class, assign values to the customer object. Before adding the values to database, we need to validate the same and create database connection, etc.
Now if we look at the code above, we can see that a person who needs to use our customer class, should first validate, then create DB objects and then only he/she can use our Add method. This seems like a very complicated procedure indeed. We need to simplify things further.
Let’s ask a question to ourselves – what does my end user need?
He just needs a customer code, a customer name and an add method. That’s all. Other granular methods just make things complex for the user. So, lets just modify our code a bit.
What we did is we made the granular methods private and call these methods from within the Add method. So now the user just needs to call the Add method, he is not exposed to the minute details of what exactly happens within the Add method.
So, to summarize, we can say that the first step in this scenario where we identified what does my end user needs is nothing but Abstraction.
Then when we went into the minute details of the implementation we ended up with other methods and logic etc to implement this functionality, but we ended up with a very complex interface.
So, to make things better, we modified our code by exposing only what is required to the end user and making the other methods as private. This is nothing but Encapsulation.
Inheritance is the ability to create a class from another class, the “parent” class, extending the functionality and state of the parent in the derived, or “child” class.
Let’s understand this with a very common example used to explain inheritance.
First, we define an Animal class, with a simple method to output a greeting. Then we define a Dog class, and with a colon, we tell C# that the Dog class should inherit from the Animal class. The beautiful thing about this is that it makes sense in the real world as well – a Dog is, obviously, an Animal. Let’s try using the classes:
If you run this example, you will notice that even though we have not defined a Greet() method for the Dog class, it still knows how to greet us, because it inherits this method from the Animal class. However, this greeting is a bit anonymous, so let’s customize it when we know which animal it is:
Besides the added method on the Dog class, you should notice two things: I have added the virtual keyword to the method on the Animal class, and on the Dog class, I use the override keyword. In C#, you are not allowed to override a member of a class unless it’s marked as virtual. If you want to, you can still access the inherited method, even when you override it, using the base keyword.
The word polymorphism means having many forms. In other words, polymorphism can be expressed as ‘one interface, multiple functions’.
Polymorphism can be further classified into the following types:
a) Static Polymorphism : 1. Function overloading
b) Dynamic Polymorphism
In static polymorphism, the response to a function is determined at the compile time. Hence this is also referred to as compile time polymorphism.
As shown above, static polymorphism can be implemented in two ways:
Function overloading is multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You cannot overload function declarations that differ only by return type.
The output of the above program is:
Printing int: 8
Printing float: 22.45
Printing string: Hi There
Operator overloading is implemented by functions with special names – the keyword operator followed by the symbol for the operator being defined. Like any other function, an overloaded operator has a return type and a parameter list.
The below function implements the addition operator (+) for a user-defined class Box. It adds the attributes of two Box objects and returns the resultant Box object.
In dynamic polymorphism, the response to a function is determined at the run time. Hence this is also referred to as run time polymorphism. Dynamic polymorphism is implemented by abstract classes and virtual functions.
The output of the above program is:
Rectangle class area:Area: 70
Triangle class area:Area: 25
Now we can see from the above example that each of the child classes has overridden the parent class implementation and this type of polymorphism happens during the actual run time of the application.
Object Oriented Programming videos by Questpond