OOPS..yu did it again!!!!
Object Oriented Programming is a dreaded topic for interviews in the IT field
Here's a simple go thru with examples and explaination to help you out.
Fundamental concepts of OO Language which a language has to follow,in order to be a truly OO language.
• OBJECT
• CLASS
• ABSTRACTION
• ENCAPSULATION
• DATA HIDING / INFORMATION HIDING
• INHERITANCE
• POLYMORPHISM
Lets take a brief look into these concepts.
Objects:
Object is the basic unit of object-oriented programming. Objects are identified by its unique name. An object represents a particular instance of a class. There can be more than one instance of an object. Each instance of an object can hold its own relevant data.
An Object is a collection of data members and associated member functions also known as methods.
Classes:
Classes are data types based on which objects are created. Objects with similar properties and methods are grouped together to form a Class. Thus a Class represent a set of individual objects. Characteristics of an object are represented in a class as Properties. The actions that can be performed by objects becomes functions of the class and is referred to as Methods.
For example consider we have a Class of Cars under which Santro Xing, Alto and WaganR represents individual Objects. In this context each Car Object will have its own, Model, Year of Manufacture, Colour, Top Speed, Engine Power etc., which form Properties of the Car class and the associated actions i.e., object functions like Start, Move, Stop form the Methods of Car Class.
No memory is allocated when a class is created. Memory is allocated only when an object is created, i.e., when an instance of a class is created.
In the software world, though you may not have realized it, you have already used classes. For example, the TextBox control, you always used, is made out of the TextBox class, which defines its appearance and capabilities. Each time you drag a TextBox control, you are actually creating a new instance of the TextBox class.
Example: Car object
– State
• Current Speed • Current Gear • Engine State (Running, Not Running)
– Behavior (Acts on the object and changes state)
• Slow down • Accelerate • Stop • Switch Off Engine • Start Engine
Abstraction:
Abstraction means hiding complex details of creation(logic and functions) and just implement/call them without bothering about how they work?.Abstraction focuses the outside view of an object/concept. As an example, consider the vector in standard library. You want to create a vector with a given size (constructor), enlarge or grow the vector (push_back), accesing to elements (operator[]) and ... It is less
important to know ,how vector is internally implemented. You may use vector
for years, but you probably don't know how vector is implemented.
Real Time Example: TV Remote Control
We use it for switch on , switch off , increase or decrease volume , select a particular channel etc. without bothering how it works internally.
Abstraction in real life means "showing only what is necessary and hiding whatever unnecessary". C++ implements this by putting a seperation between properties of datatypes which are visible and the associated implementation details which are hidden.
Eg:
--- A touch screen at railway station or ATM machine
In these devices we just use the touch screen application to satisfy our needs, we dont see what is happening inside its software.
--- A class Car would be made up of an Engine, Gearbox, Steering objects, and many more components. To build the Car class, one does not need to know how the different components work internally, but only how to interface with them, i.e., send messages to them, receive messages from them etc.
Encapsulation:
Encapsulation means combining both data and function that operates on that data into a single unit i.e. class.Encapsulation is the mechanism that binds together the code and the data it manipulates, and keeps both safe from outside interference and misuse. A car’s dashboard hides the complexity and internal workings of its engine.
Data Hiding means to make data invisible to external functions to minimize accidental modification/change of important data.
Some other common definitions
1. Insulation of data from direct access by the program.when we put data and methods in a context,say,a class , we have achieved encapsulation but when we use public/private/protected keywords, we acheive Information hiding.Following is the best example of all the three
class employee /* Encapsultaion*/
{
private:
char name[20];
int age;
float salary;
public: /* Data Hiding, Following functions access data */
void getemployee
{
cout<< "Enter name";
cin>>name;
cout<<"Enter Age";
cin>>age;
cout<< "Enter Salary";
cin>>salary;
}
void showemployee
{
cout<<"\n Name"<<name;
cout<<"\n Age"<<age;
cout<<"\n Salary"<<salary;
}
};
void main()
{
/*Abstraction:- working defined in employee class*/
employee e1;
e1.getemployee(); // abstraction
e1.showemployee(); // abstraction
}
Method:-
An object's abilities. In language, methods are verbs. Lassie
, being a Dog
, has the ability to bark. So bark()
is one of Lassie
's methods. She may have other methods as well, for example sit()
or eat()
or walk()
. Within the program, using a method usually affects only one particular object; all Dog
s can bark, but you need only one particular dog to do the barking.
Message Passing:-
“The process by which an object sends data to another object or asks the other object to invoke a method” .
E.g. the object called Student
may communicate with Course
object to know how many courses are there by invoking Course's
'getCount' method.
Inheritance:
Defining new classes from the existing one. The new class will get all the methods and properties of the existing class. The new class known as sub class / child class / derived class. The existing class known as super class / parent class / base class.
Inheritance is implied by “is-a” or “kind-of” relationship. Inheritance is basically used for reuse the code and focus to make generic kind of thing rather than specific one.
Some other common definitions
1. An object can acquire the properties of another object.
As an example you can say that both IOException and SecurityException are of type Exception. They have all characteristics and behaviors of an Exception, That mean the IOException is a specialized kind of Exception. A SecurityException is also an Exception. As such, we expect it to share certain characteristic with IOException that are generalized in Exception, but to differ in those characteristics that are specialized in SecurityExceptions. In other words, Exception generalizes the shared characteristics of both IOException and SecurityException, while IOException and SecurityException specialize with their characteristics and behaviors.
In OOP, the specialization relationship is implemented using the principle called inheritance.
Polymorphism:
Ability to acquire different forms.
Static or compile-time Polymorphism / early binding
Static Polymorphism is the use of one method signature, or one operator such as "+", to perform several different functions depending on the implementation. The "+" operator, for example, may be used to perform integer addition, float addition, list concatenation, or string concatenation. Any two subclasses of Number, such as Integer and Double, are expected to add together properly in an OOP language. The language must therefore overload the addition operator, "+", to work this way. This helps improve code readability.
Runtime or dynamic Polymorphism / late binding
An Object is in different forms and in each form its exhibit the same functionality but the implementation is different.Single Form behaving differently in different Situations.
Example:-
1. Man: Man at Home act as husband/son, in Office acts as an Employee, in Public acts as a Good Citizen.
2. Output Device (parent class) Functionality :- display()
-- Monitor form , overrides “display()” for display on the console.
-- Printer form , overrides “display()” for display on the paper.
-- LCD form, overrides “display()” for display on the screen.
• References are all the same, but objects are not
• Method invoked is that associated with the OBJECT, NOT with the reference.
There are basically two types of polymorphism. Compile Time (also knows as Early binding) and Run Time (also knows as Late binding) Polymorphism.
In Compile Time Polymorphism Here compiler knows which object , you are working with. Overloading is a compile time polymorphism. In Overloading method should have same name with different arguments. Simple example of overloading is if you have scenario in which you want to add 2 numbers or characters or strings or doubles. You can have 4 methods with the same name “add” , but with different arguments.
In Run Time Polymorphism, Here compiler doesn’t know to which object parent class pointer or reference referring to . It is known during runtime only. Overriding or inheritance-based polymorphism are kind of polymorphism. Simple and very common is, if you have a class shape which is inherited to Triangle, Square and Circle classes. Shape class has a virtual method name as “Draw” which will definitely inherited to all inherited class. All sub classes i.e. Triangle, Square and Circle can override “Draw”. Now, if you declare a pointer or reference of shape class and initialize it with any of the inherited class it will call the method of inherited class.
Some other common definitions
1. One name many forms.
2. One interface multiple methods / ways.
Association , Aggregation and Composition
In Object-oriented programming, Association defines a relationship between classes of objects which allows one object instance to cause another to perform an action on its behalf. It means "sending a message (message passing)", "invoking a method" or "calling a member function" to the controlled object.
For a given association between object A and object B, there can be three possible categories .
- One to One. Exactly one instance of Class A is associated with exactly one instance of Class B and vice versa. Example: A department has exactly one Head and One Head can lead only one department .
- One to Many : One instance of Class A can have many instance of Class B. From perspective of Class B, there can be only one Class A Example : A department employees many Professors, but a professor works only for one department
- Many to Many : For a given instance of Class A there can be many instance of Class B and From Class B perspective there can be many instances of Class A. Example : A student enrolls in many courses and a course has many students .
An aggregation is a specific type of composition where no ownership between the complex object and the subobjects is implied. When an aggregate is destroyed, the subobjects are not destroyed.
For example, consider the math department of a school, which is made up of one or more teachers. Because the department does not own the teachers (they merely work there), the department should be an aggregate. When the department is destroyed, the teachers should still exist independently (they can go get jobs in other departments).
Because aggregations are just a special type of compositions, they are implemented almost identically, and the difference between them is mostly semantic. In a composition, we typically add classes to the composition using either normal variables or pointers where
the allocation and deallocation process is handled by the
composition class itself.
Let’s take a look at our Teacher and Department example in more detail.
#include <string>
using namespace std;
class Teacher
{
private:
string m_strName;
public:
Teacher(string strName)
: m_strName(strName)
{
}
string GetName() { return m_strName; }
};
class Department
{
private:
Teacher *m_pcTeacher; // This dept holds only one teacher
public:
Department(Teacher *pcTeacher=NULL)
: m_pcTeacher(pcTeacher)
{
}
};
int main() { // Create a teacher outside the scope of the Department Teacher *pTeacher = new Teacher("Bob"); // create a teacher { // Create a department and use the constructor parameter to pass the teacher to it. Department cDept(pTeacher); } // cDept goes out of scope here and is destroyed // pTeacher still exists here because cDept did not destroy it delete pTeacher; }
In this case, pTeacher is created independently of cDept,and then passed into cDept’s constructor. Note that the department class uses an initialization list to set the value of m_pcTeacher to the pTeacher value we passed in. When cDept is destroyed, the m_pcTeacher pointer destroyed, but pTeacher is not deallocated, so it still exists until
it is independently destroyed.
To summarize the differences between composition and aggregation:
Compositions:
Typically use normal member variables Can use pointer values if the composition class automatically handles allocation/deallocation
Responsible for creation/destruction of subclasses
Aggregations:
Typically use pointer variables that point to an object that lives outside the scope of the aggregate class.Not responsible for creating/destroying subclasses.
It is worth noting that the concepts of composition and aggregation can be mixed freely within the same class. It is entirely possible to write a class that is responsible for the creation/destruction of some subclasses but not others.
For example, our Department class could have a name and a teacher. The name would probably be added to the department by composition, and would be created and destroyed with the department. On the other hand, the teacher would be added to the department by aggregate, and created/destroyed independently.
While aggregates can be extremely useful in some cases, they are also potentially dangerous. As noted several times, aggregates are not responsible for deallocating their subobjects when they are destroyed. Consequently, if there are no other pointers or references to those subobjects when the aggregate is destroyed, those subobjects will cause a memory leak. It is up to the programmer to ensure that this does not happen. This is generally handled by ensuring other pointers or references to those subobjects exist when the aggregate is destroyed.
Composition : Defines a strong-coupled relationship between two entities, where the one entity is part of another, and both need each other for their existence. e.g. Human body and the Heart.
Aggregation : Defines a weak-coupled relationship between two entities, where one entity could be part of another, but either can exist without the other, independantly. e.g. Department and employee.
Coupling and Cohesion
Coupling:
Coupling is the degree to which one class knows about another class. If the only knowledge that class A has about class B, is what class B has exposed through its interface, then class A and class B are said to be loosely coupled... That is a good thing. If on the other hand, class A relies on parts of class B that are not part of class B's interface, then the coupling between the classes is tighter... not a good thing. In other words, if A knows more than it should about the way in which B was implemented, then A and B are tightly coupled.
If class A knows non-API stuff about class B, and class B knows non-API stuff about class A... this is Really Bad. If either class is ever changed, there's a chance that the other class will break.
Following is the example of tight coupling, which has been enabled by poor encapsulation.
class DoTaxes
{
float rate;
float doColorado()
{
SalesTaxRates str=new SalesTaxRates();
rate=str.salesRate; // bad
// instead of this , there should be a method call.
}
}
class SalesTaxRates
{
public float salesRate;//should be prv
public float adjustedSalesRate;
public float getSalesRate(String region)
{
salesRate=new DoTaxes().doColorado();
return adjustedSalesRate;
}
}
Cohesion
While coupling has to do with how classes interact with each other, cohesion is all about how a single class is designed. The term "cohesion" is used to indicate the degree to which a class has a single, well-focused purpose. Cohesion is a subjective concept. The more focused a class is, the higher its cohesiveness - a good thing. The key benefit of high cohesion is that such classes are typically much easier to maintain (and less frequently changed) than classes with low cohesion. Another benefit of high cohesion is that classes with a well-focused purpose tend to be more reusable than other classes.
e.g.
class BudgetReport
{
void connectToRdbms()
{
}
void generateBudgetReport()
{
}
void saveToFile()
{
}
void print()
{
}
}
Now imagine your manager comes along and says, "Do u know that accounting application we're working on? The clients just decided that they're also going to want to generate a revenue projection report, and they want to do some inventory report also. They do like our reporting features, however, so make sure that all of these reports will let them choose a database, choose a printer and save generated reports to data files.
Rather than putting all the printing code into one report class, we probably would have been better off with the following design right from the start:
class BudgetReport
{
Options getReportingOptions()
{
}
void generateBudgetReport(Options o)
{
}
}
class ConnectToRDBMS
{
DBconnection getRDBMS()
{
}
}
class PrintStuff
{
PrintOptions getPrintOptions()
{
}
}
class FileSaver
{
SaveOptions getFileSaveOptions()
{
}
}
This design is much more cohesive. Instead of one class that does everything, we've broken the system into four main classes, each with a very specific, or cohesive, role. Because we've built these specialized, reusable classes, it'll be much easier to write a new report, since we've already got the database connection class, the printing class, and the file saver class, and that means they can be reused by other classes that might want to print a report.