Related
Can any one describe the exact difference between loose coupling and tight coupling in Object oriented paradigm?
Tight coupling is when a group of classes are highly dependent on one another.
This scenario arises when a class assumes too many responsibilities, or when one concern is spread over many classes rather than having its own class.
Loose coupling is achieved by means of a design that promotes single-responsibility and separation of concerns.
A loosely-coupled class can be consumed and tested independently of other (concrete) classes.
Interfaces are a powerful tool to use for decoupling. Classes can communicate through interfaces rather than other concrete classes, and any class can be on the other end of that communication simply by implementing the interface.
Example of tight coupling:
class CustomerRepository
{
private readonly Database database;
public CustomerRepository(Database database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
class Database
{
public void AddRow(string Table, string Value)
{
}
}
Example of loose coupling:
class CustomerRepository
{
private readonly IDatabase database;
public CustomerRepository(IDatabase database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
interface IDatabase
{
void AddRow(string Table, string Value);
}
class Database implements IDatabase
{
public void AddRow(string Table, string Value)
{
}
}
Another example here.
Explanation without any code
Simple analogy to explain the concept. Code can come later.
Summary Example of Loose Coupling:
In the picture above, the Hat is "loosely coupled" to the body. This means you can easily take the hat off without making any changes to the person/body. When you can do that then you have "loose coupling". See below for elaboration.
Detailed Example
Think of your skin. It's stuck to your body. It fits like a glove. But what if you wanted to change your skin colour from say white to black? Can you imagine just how painful it would be to peel off your skin, dye it, and then to paste it back on etc? Changing your skin is difficult because it is tightly coupled to your body. You just can't make changes easily. You would have to fundamentally redesign a human being in order to make this possible.
Key Point #1: In other words, if you want to change the skin, you would also HAVE TO change the design of your body as well because the two are joined together - they are tightly coupled.
God was not a good object oriented programmer.
Loose coupling (Detailed Example)
Now think of getting dressed in the morning. You don't like blue? No problems: you can put a red shirt on instead. You can do this easily and effortlessly because the shirt is not really connected to your body the same way as your skin. The shirt doesn't know or care about what body it is going on. In other words, you can change your clothes, without really changing your body.
That's key point #2. If you change your shirt, then you are not forced to change your body - when you can do that, then you have loose coupling. When you can't do that, then you have tight coupling.
That's the basic concept in a nutshell.
Why is all of this important?
What do changing shirts have to do with software?
Change. It's inevitable when writing software. If we know in advance that a change is going to come in a particular place, we should loosely couple on that point: then we could make those changes easily and quickly, without bugs.....Consider some examples which might help elaborate:
Loose Coupling in Software:
CSV/JSON Examples: Early on in my career, my manager said: "give me the output as a CSV file". I created a routine that worked like a charm. Then one or two weeks later, he says: "actually, I want the output for another client in JSON".
I had to rewrite the entire thing. But this time, I rewrote it using interfaces - a loosely coupled design pattern. Now, adding new output formats, is so much easier. I can edit the JSON portions without fear I will break my CSV output.
DB Examples: if you want to switch from sqlLite to PostGreSQL easily - loosely coupled code makes it really easy to switch (i.e. to put on a red shirt instead of a blue shirt). The Rails ActiveRecord library is loosely coupled on its database implementation. This makes it super easy for someone to use their own database implementation, while using the same code base!
Cloud Provider examples: Or if you're using AWS and they start charging too much because of market dominance, you should be able to somewhat easily switch to Google or Azure etc. This is precisely the reason why libraries like Active Storage exist - they provide users with a healthy indifference as to the specific cloud provider being used (Azure, AWS S3, GCS etc.). You can easily change cloud providers with just a one-line code change. The implementation details of the cloud storage providers are loosely coupled.
Testing: if you want to test your software, with predetermined outputs and inputs - how are you going to do it? With loosely coupled software - it's a breeze: you can run your tests, and you can also deploy your production code and do it all in the same code base. With tightly coupled code, testing your production code is nearly impossible.
Do we need to make everything "loosely coupled"? Probably not. We should exercise judgement. Some amount of coupling is inevitable. But consider minimizing it if you know in advance where it will change. I would also counsel against guessing where things will change, and loosely coupling everything. Loosely couple, only when you need to.
Summary
In short, loose coupling makes code easier to change.
The answers above provide some code which is worth reading.
Advanced Topics
Loose coupling goes hand-in-hand with polymorphism and interfaces. If you like cartoons and analogies, consider some other posts I have written:
What is Polymorphism?
What is an interface?
What do you mean by 'leaky abstractions' - not written by me.
Picture Attribution.
In object oriented design, the amount of coupling refers to how much the design of one class depends on the design of another class. In other words, how often do changes in class A force related changes in class B? Tight coupling means the two classes often change together, loose coupling means they are mostly independent. In general, loose coupling is recommended because it's easier to test and maintain.
You may find this paper by Martin Fowler (PDF) helpful.
In general Tight Coupling is bad in but most of the time, because it reduces flexibility and re-usability of code, it makes changes much more difficult, it impedes testability etc.
Tightly Coupled Object is an object need to know quite a bit about each other and are usually highly dependent on each other interfaces. Changing one object in a tightly coupled application often requires changes to a number of other objects, In small application we can easily identify the changes and there is less chance to miss anything. But in large applications these inter-dependencies are not always known by every programmer or chance is there to miss changes. But each set of loosely coupled objects are not dependent on others.
In short we can say, loose coupling is a design goal that seeks to reduce the interdependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component. Loose coupling is a much more generic concept intended to increase the flexibility of a system, make it more maintainable, and make the entire framework more 'stable'.
Coupling refers to the degree of direct knowledge that one element has of another. we can say an eg: A and B, only B change its behavior only when A change its behavior. A loosely coupled system can be easily broken down into definable elements.
Tight Coupling means one class is dependent on another class.
Loose Coupling means one class is dependent on interface rather than class.
In tight coupling, there are hard-coded dependency declared in methods.
In loose coupling, we must pass dependency externally at runtime instead of hard-coded. (Loose couple systems use interface for decreased dependency with class.)
For example, we have a system that can send output in two or more ways like JSON output, CSV output, etc.
Tight Coupled
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput() {
// Here Output will be in CSV-Format, because of hard-coded code.
// This method tightly coupled with CSVOutputGenerator class, if we want another Output, we must change this method.
// Any method, that calls Class1's generateOutput will return CSVOutput, because Class1 is tight couple with CSVOutputGenerator.
OutputGenerator outputGenerator = new CSVOutputGenerator();
output.generateOutput();
}
}
In the example above, if we want to change the output in JSON, then we need to find and change in the whole code, because Class1 is tightly coupled with the CSVOutputGenerator class.
Loose Coupled
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput(OutputGenerator outputGenerator) {
// if you want to write JSON, pass object of JSONOutputGenerator (Dependency will be passed externally to this method)
// if you want to write CSV, pass object of CSVOutputGenerator (Dependency will be passed externally to this method)
// Due to loose couple with class, we don't need to change code of Class1, because Class1 is loose coupled with CSVOutputGenerator or JSONOutputGenerator class
// Any method, that calls Class1's generateOutput will desired output, because Class1 does not tight couple with CSVOutputGenerator or JSONOutputGenerator class
OutputGenerator outputGenerator = outputGenerator;
output.generateOutput();
}
}
When two objects are loosely coupled, they can interact but have very little knowledge of
each other.
Loosely coupled designs allow us to build flexible OO systems that can handle change.
Observer design pattern is a good example for making classes loosely coupled, you can have a look on it in Wikipedia.
Loose coupling means that the degree of dependency between two components is very low.
Example: GSM SIM
Tight coupling means that the degree of dependency between two components is very high.
Example: CDMA Mobile
There are a lot of nice answers here using analogies, but a friend at work gave me an example that I liked more than all of the ones mentioned here... Eyes and Glasses!
Tight Coupling
Tight coupling would be the eyes. If I want to fix my vision, it's very expensive to get an eye transplant and holds a fair amount of risk. But what if the designer (being the human race) found a better way. Add a feature that is loosely coupled to the body so it can be easily changed! (yes.. glasses)
Loose coupling
I can easily replace my glasses without breaking my underlying vision. I can take off the glasses and my vision will be how it was before (not better or worse). Using different pairs of glasses changes how we see the world through our eyes with little risk and easy maintainability.
Summary
So next time someone asks you "who cares if my code is tightly-coupled?" The answer is all about effort to change, effort to maintain and risk of change.
So how is this done in C#? Interfaces and Dependency Injection!
EDIT
This is a good example of the Decorator pattern as well, where the eyes are the class we are decorating by meeting interface requirements but giving different functionality (e.g. sunglasses, reading glasses, magnifying glasses for jewelers, etc.)
An extract from my blog post on coupling:
What is Tight Coupling:-
As par above definition a Tightly Coupled Object is an object that needs to know about other objects and are usually highly dependent on each other's interfaces.
When we change one object in a tightly coupled application often it requires changes to a number of other objects. There is no problem in a small application we can easily identify the change. But in the case of a large applications these inter-dependencies are not always known by every consumer or other developers or there is many chance of future changes.
Let’s take a shopping cart demo code to understand the tight coupling:
namespace DNSLooseCoupling
{
public class ShoppingCart
{
public float Price;
public int Quantity;
public float GetRowItemTotal()
{
return Price * Quantity;
}
}
public class ShoppingCartContents
{
public ShoppingCart[] items;
public float GetCartItemsTotal()
{
float cartTotal = 0;
foreach (ShoppingCart item in items)
{
cartTotal += item.GetRowItemTotal();
}
return cartTotal;
}
}
public class Order
{
private ShoppingCartContents cart;
private float salesTax;
public Order(ShoppingCartContents cart, float salesTax)
{
this.cart = cart;
this.salesTax = salesTax;
}
public float OrderTotal()
{
return cart.GetCartItemsTotal() * (2.0f + salesTax);
}
}
}
Problems with the above example
Tight Coupling creates some difficulties.
Here, OrderTotal() methods is give us complete amount for the current items of the carts. If we want to add the discount features in this cart system. It is very hard to do in above code because we have to make changes at every class as it is very tightly coupled.
The way I understand it is, that tightly coupled architecture does not provide a lot of flexibility for change when compared to loosely coupled architecture.
But in case of loosely coupled architectures, message formats or operating platforms or revamping the business logic does not impact the other end. If the system is taken down for a revamp, of course the other end will not be able to access the service for a while but other than that, the unchanged end can resume message exchange as it was before the revamp.
There are certain tools that provide dependency injection through their library, for example in .net we have ninject Library .
If you are going further in java then spring provides this capabilities.
Loosly coupled objects can be made by introducing Interfaces in your code, thats what these sources do.
Say in your code you are writing
Myclass m = new Myclass();
now this statement in your method says that you are dependent on myclass this is called a tightly coupled. Now you provide some constructor injection , or property injection and instantiating object then it will become loosly coupled.
It's about classes dependency rate to another ones which is so low in loosely coupled and so high in tightly coupled. To be clear in the service orientation architecture, services are loosely coupled to each other against monolithic which classes dependency to each other is on purpose
Loose coupling is and answer to to old style hardcoded dependencies and related issues issues like frequent recompilation when anything changes and code reuse. It stresses on implementing the worker logic in components and avoiding solution specific wire up code there.
Loose Coupling = IoC
See this for easier explanation.
Loose Coupling is the process of giving the dependency your class needs indirectly without providing all the information of the dependency(i.e in the from of interface) in case tight coupling you directly give in the dependency which is not good way of coding.
If an object's creation/existence dependents on another object which can't be tailored, its tight coupling. And, if the dependency can be tailored, its loose coupling. Consider an example in Java:
class Car {
private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
// Other parts
public Car() {
// implemenation
}
}
The client of Car class can create one with ONLY "X_COMPANY" engine.
Consider breaking this coupling with ability to change that:
class Car {
private Engine engine;
// Other members
public Car( Engine engine ) { // this car can be created with any Engine type
this.engine = engine;
}
}
Now, a Car is not dependent on an engine of "X_COMPANY" as it can be created with types.
A Java specific note: using Java interfaces just for de-coupling sake is not a proper desing approach. In Java, an interface has a purpose - to act as a contract which intrisically provides de-coupling behavior/advantage.
Bill Rosmus's comment in accepted answer has a good explanation.
Loose and Tight coupling is about dependency one program component from another. This means dependency not only with programming class, it is about programming system components at all.
For example if you use only simple raw SQL Query to receive data from SQL Server this is Loose coupling. The opposite of Loose Coupling and simple raw SQL Query is Tight Coupling and Entity Framework Core. In Entity Framework Core you have to full model with POCO class in your code reflect database structure, than means any changing in database you have to reflect in code.
So, Tight Coupling between program code and database structure is Entity Framework, the opposite of this approach is refuse to use any ORM and refuse to have full mirror database structures in your program code.
I am developing a class library which will include the object Car.
The dilemma is, Car itself will be a class with fields such as Registration Number, and other general information on the car.
But a car has an engine, chassis, etc. These objects need to be modelled too. Should they be classes embedded within Car? If not, what is the usage scenario of an embedded class?
I've learnt that composition is "part of", so you can model seperate classes and use the engine type, for example, at the field level of the car to achieve this. However, "aggregation", which is a "has a" relationship with the type being passed in the ctor, also applies (a car "has an" engine).
Which way do I go?
EDIT: I am currently on homework hence the lack of a reply from me. The class library is for a web app based around cars. I am a professional developer (I develop in .NET for a living but as a junior) so this is not a homework question.
Thanks
It really depends on your application.
For example, you could implement the wheels as separate classes, containing information about what tyre is on it, how worn it is, etc. but if your app doesn't even care about the wheels then the entire class is a waste of code.
I can see three use cases for composition:
The owning class has gotten overly complicated and should be broken down.
The owning class has multiple copies of a set of properties that could be mapped into a class. This allows you to bind all those properties together.
The contained object may need to be inspected or considered separately from the object that owns it (eg. you might want to move the Engine object to another car) or may be replaced as a single unit.
In summary: Use composition as a tool for encapsulating complexity or eliminating repetition. If it doesn't serve one of those purposes it probably isn't worth making a new class for.
A class should have as few responsibilities as possible and encapsulate and delegate other functionality to other classes. Lots of a small, simple classes that do one thing is a sign of a readable, stable codebase.
Yes, a car will "have" an engine, but I'd suggest using an interface for this and similar "has a" relationships. Again, depending on the professor, you might get bonus points for having a factory create different cars (appropriate, no?):
public class Car
{
private Engine engine;
public Car(Engine engine)
{
this.engine = engine;
}
public void accelerate()
{
this.engine.goFaster();
}
public void decelerate()
{
this.engine.goSlower();
}
}
public interface Engine
{
public void goFaster();
public void goSlower();
}
public class ReallyFastEngine implements Engine
{
public void goFaster()
{
// some code that goes really fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class NotAsFastEngine implements Engine
{
public void goFaster()
{
// some code that goes not as fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class CarFactory()
{
public static Car createFastCar()
{
return new Car(new ReallyFastEngine());
}
public static Car createNotAsFastCar()
{
return new Car(new NotAsFastEngine());
}
}
Seeing as it is homework, and depending on the inclinations of your tutor/professor/teacher, you are probably better to go down the route of writing a separate classes for the engine, wheels and so on. Even though it may be completely over-engineered, and your application may not care about them, it is possible that your homework will be marked by standards such as:
"Did they identify an engine class"
"Does it have sensible methods like Start()"
"Mark them down for lumping everything in one big class that is actually simpler, because they clearly don't understand composition"
Or whatever, and not the kinds of standards that the more pragmatic people in this thread apply to their own designs.
Only break down the model of the car into pieces that will be exposed as separate entities outside the scope of the car. Another way to think about it is do you really understand how your car gets started when you turn the key? As far as the typical driver is concerned, everything under the hood is one big (and noisy) black box. The auto-engineers know the common parts that need maintenance by the car owner and have explicitly designed them for a different level of user interaction, things like the oil dipstick or coolant reservoir refill cap.
Can you model each piece of the car? Sure. Is it helpful to model the individual spark plugs? Probably not.
Do you need cars with different attributes like color or size? Do you need cars with different capabilities like passenger or towing capacity? The one place that is different is if you need cars with different behaviors. This is where you really need to think about modeling a Driver object which has attributes, from simple ones like reaction-time to complex ones like aggressiveness.
Modeling vehicles as examples of object orientation or inheritance is problematic because the examples don't really explain the true distinctions between essential attributes that define a class. It's not new to StackOverflow but this question isn't a duplicate either, see this SO thread. I had this same discussion with a friend of mine and posted a log of it on my blog. Read up on the different aircraft types the FAA recognizes and how the regulations for each type are subdivided. There are lots of different types of aircraft, the biggest separation is between powered and unpowered.
Check out the definitions used by the FAA:
Aircraft means a device that is used
or intended to be used for flight in
the air.
Airplane means an engine-driven
fixed-wing aircraft heavier than air,
that is supported in flight by the
dynamic reaction of the air against
its wings.
Airship means an engine-driven
lighter-than-air aircraft that can be
steered.
There is also lighter-than-air and heavier-than-air. A hot-air balloon is unpowered and lighter-than-air. A blimp is powered and lighter-than-air. A glider is unpowered and heavier-than-air. A Boeing 757 is powered and heavier-than air but adds another category of 'fixed-wing' which is unlike a helicopter which is also powered and heavier-than-air but is 'rotary-wing'.
Here is the first four in the form of a table:
| Powered | Unpowered
---------------------------------------------------
Lighter-than-air | Blimp | Hot-air balloon
Heavier-than-air | 737 | Glider
You get the picture.
You can't just say you'll model the engine separately from the car because a car without an engine might be a whole different animal. A car without an engine is nothing like a trailer, which also doesn't have an engine but never will either. In these cases neither 'is-a' nor 'has-a' fits in the concrete way we build objects. You don't declare a blimp as being a aircraft that 'is-a' lighter-than-air, so is a hot-air balloon. The fact that they are both lighter-than-air doesn't make them related in any way except the physics they exploit. The distinction is important because the rules and regulations that apply are different. From the other angle, we don't describe a blimp as a hot-air balloon that 'has-a' engine. The aircraft aren't physically related, the relationship is how they should be handled.
If you don't need to define your objects to that level of detail, you may not need to model them to that level of detail either.
Car will be an top hierarchy object. Including simple fields like Number, ID or description.
And will have complicated fields like Engine, which is an object by itself.
So the Car will look something like:
class Car{
String ID;
Engine engine;
}
That a has-a relation.
One criteria you can have to decide whether the classes for Engine, Chasis etc.
needs to be present as an inner class (embedded class) is whether instance of
these classes can be used elsewhere in your application. In such cases the
decision is simple and it is to make these classes exist separately
(not as inner classes).
Even if these classes are not used elsewhere in your application then other
criteria can be testability. With these classes embedded inside and with your
design is it possible to have unit tests that can appropriately test your
code providing a good coverage.
For example say, if you have made an instance variable which references an
Engine object and this variable is being initialized in the Constructor of Car.And
your Engine class has some methods which needs to be tested. Then how can
you add unit tests to check the code in Engine class ? Probably you would
have some methods in Car class which expose the behavior or Engine class allowing
you to write unit tests. Then the question is if there is a need to expose
the behavior of Engine class wouldn't it be better that the Engine class
stands on it own?
Alternatively there might not be a need to explicitly test the methods in
Engine class and unit testing the methods in Car covers the Engine class code
as well. Then it reflects tight integration of Engine class with the Car class
and would mean it can remain as an inner class.
It depends on what it is you're trying to do. Trying to design a 'Car' class (or any other class for that matter) without an idea of the use cases is an exercise in futility.
You will design the classes and their relationships and interactions very differently depending on the use cases you're trying to enable.
I saw this in someone's code and thought wow, that's an elegant way to solve this particular problem, but it probably violates good OO principles in an epic way.
In the constructor for a set of classes that are all derived from a common base class, he requires a reference to the instancing class to be passed. For example,
Foo Foo_i = new(this);
Then later on Foo would call methods in the instancing class to get information about itself and the other objects contained by the instancing class.
On the one hand, this simplifies a TON of code that models a 5-layer tree structure in hardware (agents plugged into ports on multiple switches, etc). On the other hand, these objects are pretty tightly coupled to each other in a way that seems pretty wrong, but I don't know enough about OOA&D to put my finger on it.
So, is this okay? Or is this the OO equivalent to a goto statement?
You shoud try to avoid mutual references (especially when implemeting containment) but oftentimes they are impossible to avoid. I.e. parent child relationship - children often need to know the parent and notify it if some events happen. If you really need to do that - opt for interfaces (or abstract classes in case of C++).
So you instancing class should implement some interface, and the instanciated class should know it only as interface - this will sigificantly reduce coupling. In some respect this approach is similar to nested listener class as it exposes only part of the class, but it is easier to maintain. Here is little C# example:
interface IParent
{
//some methods here
}
class Child
{
// child will know parent (instancing class) as interface only
private readonly IParent parent_;
public Child(IParent parent)
{
parent_ = parent;
}
}
class Parent : IParent
{
// IParent implementation and other methods here
}
This sounds like it could be violating the Law of Demeter, depending on how much Foo needs to know to fish around in the instancing class. Objects should preferably be loosely coupled. You'd rather not have one class need to know a lot about the structure of another class. One example I've heard a few times is that you wouldn't hand your wallet over to a store clerk and let him fish around inside. Your wallet is your business, and you'll find what you need to give the clerk and hand it over yourself. You can reorganize your wallet and nobody will be the wiser. Looser coupling makes testing easier. Foo should ideally be testable without needing to maintain a complex context.
I try and avoid this if I can just from an information hiding point of view. The less information a class has or needs the easier it is to test and verify. That being said, it does lead to more elegant solutions in some cases so if not doing it is horribly convoluted involving an awful lot of parameter passing then by all means go for it.
Java for example uses this a lot with inner classes:
public class Outer {
private class Inner {
public Inner() {
// has access to the members of Outer for the instance that instantiated it
}
}
}
In Java, I remember avoiding this once by subclassing certain Listeners and Adapters in my controller and adding those listeners and adapters to my subclasses.
In other words my controller was
class p {
private member x
private methods
private class q {
// methods referencing p's private members and methods
}
x.setListener(new q());
}
I think this is more loosely coupled, but I would also like some confirmation.
This design pattern can make a lot of sense in some situations. For example, iterators are always associated with a specific collection, so it makes sense for the iterator's constructor to require a collection.
You didn't provide a concrete example, but if the class reminds you of goto, it probably is a bad idea.
You said the new object must interrogate the instantiating object for information. Perhaps the class makes too many assumptions about its environment? If those assumptions complicate unit testing, debugging, or (non-hypothetical) code reuse, then you should consider refactoring.
But if the design saves developer time overall and you don't expect an unmaintainable beast in two years' time, the practice is completely acceptable from a practical standpoint.
What is the precise difference between encapsulation and abstraction?
Most answers here focus on OOP but encapsulation begins much earlier:
Every function is an encapsulation; in pseudocode:
point x = { 1, 4 }
point y = { 23, 42 }
numeric d = distance(x, y)
Here, distance encapsulates the calculation of the (Euclidean) distance between two points in a plane: it hides implementation details. This is encapsulation, pure and simple.
Abstraction is the process of generalisation: taking a concrete implementation and making it applicable to different, albeit somewhat related, types of data. The classical example of abstraction is C’s qsort function to sort data:
The thing about qsort is that it doesn't care about the data it sorts — in fact, it doesn’t know what data it sorts. Rather, its input type is a typeless pointer (void*) which is just C’s way of saying “I don't care about the type of data” (this is also called type erasure). The important point is that the implementation of qsort always stays the same, regardless of data type. The only thing that has to change is the compare function, which differs from data type to data type. qsort therefore expects the user to provide said compare function as a function argument.
Encapsulation and abstraction go hand in hand so much so that you could make the point that they are truly inseparable. For practical purposes, this is probably true; that said, here’s an encapsulation that’s not much of an abstraction:
class point {
numeric x
numeric y
}
We encapsulate the point’s coordinate, but we don’t materially abstract them away, beyond grouping them logically.
And here’s an example of abstraction that’s not encapsulation:
T pi<T> = 3.1415926535
This is a generic variable pi with a given value (π), and the declaration doesn’t care about the exact type of the variable. Admittedly, I’d be hard-pressed to find something like this in real code: abstraction virtually always uses encapsulation. However, the above does actually exist in C++(14), via variable templates (= generic templates for variables); with a slightly more complex syntax, e.g.:
template <typename T> constexpr T pi = T{3.1415926535};
Many answers and their examples are misleading.
Encapsulation is the packing of "data" and "functions operating on that data" into a single component and restricting the access to some of the object's components.
Encapsulation means that the internal representation of an object is generally hidden from view outside of the object's definition.
Abstraction is a mechanism which represent the essential features without including implementation details.
Encapsulation:-- Information hiding.
Abstraction:-- Implementation hiding.
Example (in C++):
class foo{
private:
int a, b;
public:
foo(int x=0, int y=0): a(x), b(y) {}
int add(){
return a+b;
}
}
Internal representation of any object of foo class is hidden outside of this class. --> Encapsulation.
Any accessible member (data/function) of an object of foo is restricted and can only be accessed by that object only.
foo foo_obj(3, 4);
int sum = foo_obj.add();
Implementation of method add is hidden. --> Abstraction.
Encapsulation is hiding the implementation details which may or may not be for generic or specialized behavior(s).
Abstraction is providing a generalization (say, over a set of behaviors).
Here's a good read: Abstraction, Encapsulation, and Information Hiding by Edward V. Berard of the Object Agency.
encapsulation puts some things in a box and gives you a peephole; this keeps you from mucking with the gears.
abstraction flat-out ignores the details that don't matter, like whether the things have gears, ratchets, flywheels, or nuclear cores; they just "go"
examples of encapsulation:
underpants
toolbox
wallet
handbag
capsule
frozen carbonite
a box, with or without a button on it
a burrito (technically, the tortilla around the burrito)
examples of abstraction:
"groups of things" is an abstraction (which we call aggregation)
"things that contains other things" is an abstraction (which we call composition)
"container" is another kind of "things that contain other things" abstraction; note that all of the encapsulation examples are kinds of containers, but not all containers exhibit/provide encapsulation. A basket, for example, is a container that does not encapsulate its contents.
Encapsulation means-hiding data like using getter and setter etc.
Abstraction means- hiding implementation using abstract class and interfaces etc.
Abstraction is generalized term. i.e. Encapsulation is subset of Abstraction.
Abstraction
Encapsulation
It solves an issue at the design level.
Encapsulation solves an issue at implementation level.
hides the unnecessary detail but shows the essential information.
It hides the code and data into a single entity or unit so that the data can be protected from the outside world.
Focuses on the external lookout.
Focuses on internal working.
Lets focus on what an object does instead of how it does it.
Lets focus on how an object does something.
Example: Outer look of mobile, like it has a display screen and buttons.
Example: Inner details of mobile, how button and display screen connect with each other using circuits.
Example: The solution architect is the person who creates the high-level abstract technical design of the entire solution, and this design is then handed over to the the development team for implementation.
Here, solution architect acts as a abstract and development team acts as a Encapsulation.
Example: Encapsulation(networking) of user data
image courtesy
Abstraction (or modularity) – Types enable programmers to think at a higher level than the bit or byte, not bothering with low-level implementation. For example, programmers can begin to think of a string as a set of character values instead of as a mere array of bytes. Higher still, types enable programmers to think about and express interfaces between two of any-sized subsystems. This enables more levels of localization so that the definitions required for interoperability of the subsystems remain consistent when those two subsystems communicate.
Source
Java example
A lot of good answers are provided above but I am going to present my(Java) viewpoint here.
Data Encapsulation simply means wrapping and controlling access of logically grouped data in a class. It is generally associated with another keyword - Data Hiding. This is achieved in Java using access modifiers.
A simple example would be defining a private variable and giving access to it using getter and setter methods or making a method private as it's only use is withing the class. There is no need for user to know about these methods and variables.
Note : It should not be misunderstood that encapsulation is all about data hiding only. When we say encapsulation, emphasis should be on grouping or packaging or bundling related data and behavior together.
Data Abstraction on the other hand is concept of generalizing so that the underneath complex logic is not exposed to the user. In Java this is achieved by using interfaces and abstract classes.
Example -
Lets say we have an interface Animal and it has a function makeSound(). There are two concrete classes Dog and Cat that implement this interface. These concrete classes have separate implementations of makeSound() function. Now lets say we have a animal(We get this from some external module). All user knows is that the object that it is receiving is some Animal and it is the users responsibility to print the animal sound. One brute force way is to check the object received to identify it's type, then typecast it to that Animal type and then call makeSound() on it. But a neater way is to abstracts thing out. Use Animal as a polymorphic reference and call makeSound() on it. At runtime depending on what the real Object type is proper function will be invoked.
More details here.
Complex logic is in the circuit board which is encapsulated in a touchpad and a nice interface(buttons) is provided to abstract it out to the user.
PS: Above links are to my personal blog.
These are somewhat fuzzy concepts that are not unique to Computer Science and programming. I would like to offer up some additional thoughts that may help others understand these important concepts.
Short Answer
Encapsulation - Hiding and/or restricting access to certain parts of a system, while exposing the necessary interfaces.
Abstraction - Considering something with certain characteristics removed, apart from concrete realities, specific objects, or actual instances, thereby reducing complexity.
The main similarity is that these techniques aim to improve comprehension and utility.
The main difference is that abstraction is a means of representing things more simply (often to make the representation more widely applicable), whereas encapsulation is a method of changing the way other things interact with something.
Long Answer
Encapsulation
Here's an example of encapsulation that hopefully makes things more clear:
Here we have an Arduino Uno, and an Arduino Uno within an enclosure. An enclosure is a great representation of what encapsulation is all about.
Encapsulation aims to protect certain components from outside influences and knowledge as well as expose components which other things should interface with. In programming terms, this involves information hiding though access modifiers, which change the extent to which certain variables and/or properties can be read and written.
But beyond that, encapsulation also aims to provide those external interfaces much more effectively. With our Arduino example, this could include the nice buttons and screen which makes the user's interaction with the device much simpler. They provide the user with simple ways to affect the device's behavior and gain useful information about its operation which would otherwise be much more difficult.
In programming, this involves the grouping of various components into a separable construct, such as a function, class, or object. It also includes providing the means of interacting with those constructs, as well as methods for gaining useful information about them.
Encapsulation helps programmers in many many additional ways, not least of which is improved code maintainability and testability.
Abstraction
Although many other answers here defined abstraction as generalization, I personally think that definition is misguided. I would say that generalization is actually a specific type of abstraction, not the other way around. In other words, all generalizations are abstractions, but all abstractions are not necessarily generalizations.
Here's how I like to think of abstraction:
Would you say the image there is a tree? Chances are you would. But is it really a tree? Well, of course not! It's a bunch of pixels made to look like something we might call a tree. We could say that it represents an abstraction of a real tree. Notice that several visual details of the tree are omitted. Also, it does not grow, consume water, or produce oxygen. How could it? it's just a bunch of colors on a screen, represented by bytes in your computer memory.
And here is the essence of abstraction. It's a way of simplifying things so they are easier to understand. Every idea going through your head is an abstraction of reality. Your mental image of a tree is no more an actual tree than this jpeg is.
In programming, we might use this to our advantage by creating a Tree class with methods for simulated growing, water consuming, and oxygen production. Our creation would be something that represents our experience of actual trees, and only includes those elements that we really care about for our particular simulation. We use abstraction as a way of representing our experience of something with bytes and mathematics.
Abstract Classes
Abstraction in programming also allows us to consider commonalities between several "concrete" object types (types that actually exist) and define those commonalities within a unique entity. For example, our Tree class may inherit from an abstract class Plant, which has several properties and methods which are applicable to all of our plant-like classes, but removes those that are specific to each type of plant. This can significantly reduce duplication of code, and improves maintainability.
The practical difference of an abstract class and plain class is that conceptually there's no "real" instances of the abstract class. It wouldn't make sense to construct a Plant object because that's not specific enough. Every "real" Plant is also a more specific type of Plant.
Also, if we want our program to be more realistic, we might want to consider the fact that our Tree class might be too abstract itself. In reality, every Tree is a more specific type of Tree, so we could create classes for those types such as Birch, Maple, etc. which inherit from our, perhaps now abstract, Tree class.
JVM
Another good example of abstraction is the Java Virtual Machine (JVM), which provides a virtual or abstract computer for Java code to run on. It essentially takes away all of the platform specific components of a system, and provides an abstract interface of "computer" without regard to any system in particular.
The Difference
Encapsulation differs from abstraction in that it doesn't have anything to do with how 'real' or 'accurate' something is. It doesn't remove components of something to make it simpler or more widely applicable. Rather it may hide certain components to achieve a similar purpose.
Abstraction lets you focus on what the object does instead of how it does it
Encapsulation means hiding the internal details or mechanics of how an object does something.
Like when you drive a car, you know what the gas pedal does but you may not know the process behind it because it is encapsulated.
Let me give an example in C#. Suppose you have an integer:
int Number = 5;
string aStrNumber = Number.ToString();
you can use a method like Number.ToString() which returns you characters representation of the number 5, and stores that in a string object. The method tells you what it does instead of how it does it.
Encapsulation: Is hiding unwanted/un-expected/propriety implementation details from the actual users of object.
e.g.
List<string> list = new List<string>();
list.Sort(); /* Here, which sorting algorithm is used and hows its
implemented is not useful to the user who wants to perform sort, that's
why its hidden from the user of list. */
Abstraction: Is a way of providing generalization and hence a common way to work with objects of vast diversity. e.g.
class Aeroplane : IFlyable, IFuelable, IMachine
{ // Aeroplane's Design says:
// Aeroplane is a flying object
// Aeroplane can be fueled
// Aeroplane is a Machine
}
// But the code related to Pilot, or Driver of Aeroplane is not bothered
// about Machine or Fuel. Hence,
// pilot code:
IFlyable flyingObj = new Aeroplane();
flyingObj.Fly();
// fighter Pilot related code
IFlyable flyingObj2 = new FighterAeroplane();
flyingObj2.Fly();
// UFO related code
IFlyable ufoObj = new UFO();
ufoObj.Fly();
// **All the 3 Above codes are genaralized using IFlyable,
// Interface Abstraction**
// Fly related code knows how to fly, irrespective of the type of
// flying object they are.
// Similarly, Fuel related code:
// Fueling an Aeroplane
IFuelable fuelableObj = new Aeroplane();
fuelableObj.FillFuel();
// Fueling a Car
IFuelable fuelableObj2 = new Car(); // class Car : IFuelable { }
fuelableObj2.FillFuel();
// ** Fueling code does not need know what kind of vehicle it is, so far
// as it can Fill Fuel**
Difference Between Abstraction and Encapsulation.
Abstraction: The idea of presenting something in a simplified / different way, which is either easier to understand and use or more pertinent to the situation.
Consider a class that sends an email... it uses abstraction to show itself to you as some kind of messenger boy, so you can call emailSender.send(mail, recipient). What it actually does - chooses POP3 / SMTP, calling servers, MIME translation, etc, is abstracted away. You only see your messenger boy.
Encapsulation: The idea of securing and hiding data and methods that are private to an object. It deals more with making something independent and foolproof.
Take me, for instance. I encapsulate my heart rate from the rest of the world. Because I don't want anyone else changing that variable, and I don't need anyone else to set it in order for me to function. Its vitally important to me, but you don't need to know what it is, and you probably don't care anyway.
Look around you'll find that almost everything you touch is an example of both abstraction and encapsulation. Your phone, for instance presents to you the abstraction of being able to take what you say and say it to someone else - covering up GSM, processor architecture, radio frequencies, and a million other things you don't understand or care to. It also encapsulates certain data from you, like serial numbers, ID numbers, frequencies, etc.
It all makes the world a nicer place to live in :D
Abstraction: Only necessary information is shown. Let's focus on the example of switching on a computer. The user does not have to know what goes on while the system is still loading (that information is hidden from the user).
Let's take another example, that of the ATM. The customer does not need to know how the machine reads the PIN and processes the transaction, all he needs to do is enter the PIN, take the cash and leave.
Encapsulation: Deals with hiding the sensitive data of a clas hence privatising part of it. It is a way of keeping some information private to its clients by allowing no access to it from outside.
Another example:
Suppose I created an immutable Rectangle class like this:
class Rectangle {
public:
Rectangle(int width, int height) : width_(width), height_(height) {}
int width() const { return width_; }
int height() const { return height_; }
private:
int width_;
int height_;
}
Now it's obvious that I've encapsulated width and height (access is somehow restricted), but I've not abstracted anything (okay, maybe I've ignored where the rectangle is located in the coordinates space, but this is a flaw of the example).
Good abstraction usually implies good encapsulation.
An example of good abstraction is a generic database connection class. Its public interface is database-agnostic, and is very simple, yet allows me to do what I want with the connection. And you see? There's also encapsulation there, because the class must have all the low-level handles and calls inside.
A mechanism that prevents the data of a particular objects safe from intentional or accidental misuse by external functions is called "data Encapsulation"
The act of representing essential features without including the background details or explanations is known as abstraction
Abstraction and Encapsulation by using a single generalized example
------------------------------------------------------------------------------------------------------------------------------------
We all use calculator for calculation of complex problems !
Abstraction : Abstraction means to show What part of functionality.
Encapsulation : Encapsulation means to hide the How part of the functionality.
Lets take a very simple example
/// <summary>
/// We have an Employee class having two properties EmployeeName and EmployeeCode
/// </summary>
public class Employee
{
public string EmplpyeeName { get; set; }
public string EmployeeCode { get; set; }
// Add new employee to DB is the main functionality, so are making it public so that we can expose it to external environment
// This is ABSTRACTION
public void AddEmployee(Employee obj)
{
// "Creation of DB connection" and "To check if employee exists" are internal details which we have hide from external environment
// You can see that these methods are private, external environment just need "What" part only
CreateDBConnection();
CheckIfEmployeeExists();
}
// ENCAPLUSATION using private keyword
private bool CheckIfEmployeeExists()
{
// Here we can validate if the employee already exists
return true;
}
// ENCAPLUSATION using private keyword
private void CreateDBConnection()
{
// Create DB connection code
}
}
Program class of Console Application
class Program
{
static void Main(string[] args)
{
Employee obj = new Employee();
obj.EmplpyeeName = "001";
obj.EmployeeCode = "Raj";
// We have exposed only what part of the functionality
obj.AddEmployee(obj);
}
}
Let's take the example of a stack. It could be implemented using an array or a linked list. But the operations it supports are push and pop.
Now abstraction is exposing only the interfaces push and pop. The underlying representation is hidden (is it an array or a linked list?) and a well-defined interface is provided. Now how do you ensure that no accidental access is made to the abstracted data? That is where encapsulation comes in. For example, classes in C++ use the access specifiers which ensure that accidental access and modification is prevented. And also, by making the above-mentioned interfaces as public, it ensures that the only way to manipulate the stack is through the well-defined interface. In the process, it has coupled the data and the code that can manipulate it (let's not get the friend functions involved here). That is, the code and data are bonded together or tied or encapsulated.
Encapsulation is wrapping up complexity in one capsule that is class & hence Encapsulation…
While abstraction is the characteristics of an object which differentiates from other object...
Abstraction can be achieved by making class abstract having one or more methods abstract. Which is nothing but the characteristic which should be implemented by the class extending it.
e.g. when you inventing/designing a car you define a characteristics like car should have 4 doors, break, steering wheel etc… so anyone uses this design should include this characteristics. Implementation is not the head each of abstraction. It will just define characteristics which should be included.
Encapsulation is achieved keeping data and the behaviour in one capsule that is class & by making use of access modifiers like public, private, protected along with inheritance, aggregation or composition. So you only show only required things, that too, only to the extent you want to show. i.e. public, protected, friendly & private ka funda……
e.g. GM decides to use the abstracted design of car above. But they have various products having the same characteristics & doing almost same functionality. So they write a class which extends the above abstract class. It says how gear box should work, how break should work, how steering wheel should work. Then all the products just use this common functionality. They need not know how the gear box works or break works or steering wheal works. Indivisual product can surely have more features like a/c or auto lock etc…..
Both are powerful; but using abstraction require more skills than encapsulation and bigger applications/products can not survive with out abstraction.
I will try to demonstrate Encapsulation in a simple way.. Lets see..
The wrapping up of data and functions into a single unit (called
class) is known as encapsulation. Encapsulation containing and hiding
information about an object, such as internal data structures and
code.
Encapsulation is -
Hiding Complexity,
Binding Data and Function together,
Making Complicated Method's Private,
Making Instance Variable's Private,
Hiding Unnecessary Data and Functions from End User.
Encapsulation implements Abstraction.
And Abstraction is -
Showing Whats Necessary,
Data needs to abstract from End User,
Lets see an example-
The below Image shows a GUI of "Customer Details to be ADD-ed into a Database".
By looking at the Image we can say that we need a Customer Class.
Step - 1: What does my Customer Class needs?
i.e.
2 variables to store Customer Code and Customer Name.
1 Function to Add the Customer Code and Customer Name into Database.
namespace CustomerContent
{
public class Customer
{
public string CustomerCode = "";
public string CustomerName = "";
public void ADD()
{
//my DB code will go here
}
Now only ADD method wont work here alone.
Step -2: How will the validation work, ADD Function act?
We will need Database Connection code and Validation Code (Extra Methods).
public bool Validate()
{
//Granular Customer Code and Name
return true;
}
public bool CreateDBObject()
{
//DB Connection Code
return true;
}
class Program
{
static void main(String[] args)
{
CustomerComponent.Customer obj = new CustomerComponent.Customer;
obj.CustomerCode = "s001";
obj.CustomerName = "Mac";
obj.Validate();
obj.CreateDBObject();
obj.ADD();
}
}
Now there is no need of showing the Extra Methods(Validate(); CreateDBObject() [Complicated and Extra method] ) to the End User.End user only needs to see and know about Customer Code, Customer Name and ADD button which will ADD the record.. End User doesn't care about HOW it will ADD the Data to Database?.
Step -3: Private the extra and complicated methods which doesn't involves End User's Interaction.
So making those Complicated and Extra method as Private instead Public(i.e Hiding those methods) and deleting the obj.Validate(); obj.CreateDBObject(); from main in class Program we achieve Encapsulation.
In other words Simplifying Interface to End User is Encapsulation.
So now the code looks like as below -
namespace CustomerContent
{
public class Customer
{
public string CustomerCode = "";
public string CustomerName = "";
public void ADD()
{
//my DB code will go here
}
private bool Validate()
{
//Granular Customer Code and Name
return true;
}
private bool CreateDBObject()
{
//DB Connection Code
return true;
}
class Program
{
static void main(String[] args)
{
CustomerComponent.Customer obj = new CustomerComponent.Customer;
obj.CustomerCode = "s001";
obj.CustomerName = "Mac";
obj.ADD();
}
}
Summary :
Step -1: What does my Customer Class needs? is Abstraction.
Step -3: Step -3: Private the extra and complicated methods which doesn't involves End User's Interaction is Encapsulation.
P.S. - The code above is hard and fast.
Abstraction--- Hiding Implementation--at Design---Using Interface/Abstract calsses
Encapsulation--Hiding Data --At Development---Using access modifiers(public/private)
From this
Difference between Encapsulation and Abstraction in OOPS
Abstraction and Encapsulation are two important Object Oriented Programming (OOPS) concepts. Encapsulation and Abstraction both are interrelated terms.
Real Life Difference Between Encapsulation and Abstraction
Encapsulate means to hide. Encapsulation is also called data hiding.You can think Encapsulation like a capsule (medicine tablet) which hides medicine inside it. Encapsulation is wrapping, just hiding properties and methods. Encapsulation is used for hide the code and data in a single unit to protect the data from the outside the world. Class is the best example of encapsulation.
Abstraction refers to showing only the necessary details to the intended user. As the name suggests, abstraction is the "abstract form of anything". We use abstraction in programming languages to make abstract class. Abstract class represents abstract view of methods and properties of class.
Implementation Difference Between Encapsulation and Abstraction
Abstraction is implemented using interface and abstract class while Encapsulation is implemented using private and protected access modifier.
OOPS makes use of encapsulation to enforce the integrity of a type (i.e. to make sure data is used in an appropriate manner) by preventing programmers from accessing data in a non-intended manner. Through encapsulation, only a predetermined group of functions can access the data. The collective term for datatypes and operations (methods) bundled together with access restrictions (public/private, etc.) is a class.
The below paragraph helped me to understand how they differ from each other:
Data encapsulation is a mechanism of bundling the data, and the
functions that use them and data abstraction is a mechanism of
exposing only the interfaces and hiding the implementation details
from the user.
You can read more here.
Information hiding is not strictly required for abstraction or encapsulation. Information might be ignored, but does not have to be hidden.
Encapsulation is the ability to treat something as a single thing, even though it may be composed of many complex parts or ideas. For example, I can say that I'm sitting in a "chair" rather than referring to the many various parts of that chair each with a specific design and function, all fitting together precisely for the purpose of comfortably holding my butt a few feet away from the floor.
Abstraction is enabled by encapsulation. Because we encapsulate objects, we can think about them as things which relate to each other in some way rather than getting bogged down in the subtle details of internal object structure. Abstraction is the ability to consider the bigger picture, removed from concern over little details. The root of the word is abstract as in the summary that appears at the top of a scholarly paper, not abstract as in a class which can only be instantiated as a derived subclass.
I can honestly say that when I plop my butt down in my chair, I never think about how the structure of that chair will catch and hold my weight. It's a decent enough chair that I don't have to worry about those details. So I can turn my attention toward my computer. And again, I don't think about the component parts of my computer. I'm just looking at a part of a webpage that represents a text area that I can type in, and I'm communicating in words, barely even thinking about how my fingers always find the right letters so quickly on the keyboard, and how the connection is ultimately made between tapping these keys and posting to this forum. This is the great power of abstraction. Because the lower levels of the system can be trusted to work with consistency and precision, we have attention to spare for greater work.
The more I read, more I got confused. So, simply here is what I understood:
Encapsulation:
We generally see a watch from outside and it's components are encapsulated inside it's body. We have some kind of control for different operations. This way of hiding details and exposing control (e.g. setting time) is encapsulation.
Abstraction:
So far we were talking about a watch. But we didn't specify what kind of watch. It could be digital or analog, for hand or wall. There are many possibilities. What we do know is, it is a watch and it tells time and that is the only thing we are interested in, the time. This way of hiding details and exposing generic feature or use case is abstraction.
class Aeroplane : IFlyable, IFuelable, IMachine
{ // Aeroplane's Design says:
// Aeroplane is a flying object
// Aeroplane can be fueled
// Aeroplane is a Machine
}
// But the code related to Pilot, or Driver of Aeroplane is not bothered
// about Machine or Fuel. Hence,
// pilot code:
IFlyable flyingObj = new Aeroplane();
flyingObj.Fly();
// fighter Pilot related code
IFlyable flyingObj2 = new FighterAeroplane();
flyingObj2.Fly();
// UFO related code
IFlyable ufoObj = new UFO();
ufoObj.Fly();
// **All the 3 Above codes are genaralized using IFlyable,
// Interface Abstraction**
// Fly related code knows how to fly, irrespective of the type of
// flying object they are.
// Similarly, Fuel related code:
// Fueling an Aeroplane
IFuelable fuelableObj = new Aeroplane();
fuelableObj.FillFuel();
// Fueling a Car
IFuelable fuelableObj2 = new Car(); // class Car : IFuelable { }
fuelableObj2.FillFuel();
// ** Fueling code does not need know what kind of vehicle it is, so far
// as it can Fill Fuel**
abstraction is hiding non useful data from users
and encapsulation is bind together data into a capsule (a class).
I think encapsulation is way that we achieve abstraction.
The process of Abstraction and Encapsulation both generate interfaces.
An interface generated via encapsulation hides implementation details.
An interface generated via abstraction becomes applicable to more data types, compared to before abstraction.
Abstraction is a contract for the implementation we are going to do. Implementation may get changed over period of time. The various implementations themselves may or may not be hidden but are Masked behind the Abstraction.
Suppose we define all the APIs of a class in an interface then ask the users of our code to depened upon the defined APIs of the interface. We are free to improve or modify the implementation only we must follow the set contract. The users are not coupled with our implementation.
We EXPOSE all the NECESSARY Rules (methods) in abstraction, the implementation of the rules are left for the implementor entities, also the implemention is not part of the abstraction. Its just the signature and declaration what makes the abstraction.
Encapsulation is simply HIDING the internal details by reducing the acess of the states and behaviors. An encapsulated class may or may not have well defined Abstraction.
java.util.List is an abstraction for java.util.ArrayList. The internal states of java.util.ArrayList being marked with non public access modifiers is encapsulation.
Edit
Suppose a class Container.nava implements IContainer , IContainer may declare methods like addElement, removeElements, contains, etc. Here IContainer represents the abstraction for its implementing class. Abstraction is declaring the APIs of the class or a module or a system to the outer world. These APIs become the contract.
That system may be or may not be developed yet. The users of the system now can depend on the declared APIs and are sure any system implementing such a contract will always adhere to the APIs declared, they will always provide tge implementation for those APIs. Once we are writing some concrete entity then deciding to hide our internal states is encapsulation
I Think Encapsulation is a way to implement abstraction. Have a look at the following link.
Abstraction and Encapsulation
The Open/Closed Principle states that software entities (classes, modules, etc.) should be open for extension, but closed for modification. What does this mean, and why is it an important principle of good object-oriented design?
It means that you should put new code in new classes/modules. Existing code should be modified only for bug fixing. New classes can reuse existing code via inheritance.
Open/closed principle is intended to mitigate risk when introducing new functionality. Since you don't modify existing code you can be assured that it wouldn't be broken. It reduces maintenance cost and increases product stability.
Specifically, it is about a "Holy Grail" of design in OOP of making an entity extensible enough (through its individual design or through its participation in the architecture) to support future unforseen changes without rewriting its code (and sometimes even without re-compiling **).
Some ways to do this include Polymorphism/Inheritance, Composition, Inversion of Control (a.k.a. DIP), Aspect-Oriented Programming, Patterns such as Strategy, Visitor, Template Method, and many other principles, patterns, and techniques of OOAD.
** See the 6 "package principles", REP, CCP, CRP, ADP, SDP, SAP
More specifically than DaveK, it usually means that if you want to add additional functionality, or change the functionality of a class, create a subclass instead of changing the original. This way, anyone using the parent class does not have to worry about it changing later on. Basically, it's all about backwards compatibility.
Another really important principle of object-oriented design is loose coupling through a method interface. If the change you want to make does not affect the existing interface, it really is pretty safe to change. For example, to make an algorithm more efficient. Object-oriented principles need to be tempered by common sense too :)
Open Closed Principle is very important in object oriented programming and it's one of the SOLID principles.
As per this, a class should be open for extension and closed for
modification. Let us understand why.
class Rectangle {
public int width;
public int lenth;
}
class Circle {
public int radius;
}
class AreaService {
public int areaForRectangle(Rectangle rectangle) {
return rectangle.width * rectangle.lenth;
}
public int areaForCircle(Circle circle) {
return (22 / 7) * circle.radius * circle.radius;
}
}
If you look at the above design, we can clearly observe that it's not
following Open/Closed Principle. Whenever there is a new
shape(Tiangle, Square etc.), AreaService has to be modified.
With Open/Closed Principle:
interface Shape{
int area();
}
class Rectangle implements Shape{
public int width;
public int lenth;
#Override
public int area() {
return lenth * width;
}
}
class Cirle implements Shape{
public int radius;
#Override
public int area() {
return (22/7) * radius * radius;
}
}
class AreaService {
int area(Shape shape) {
return shape.area();
}
}
Whenever there is new shape like Triangle, Square etc. you can easily
accommodate the new shapes without modifying existing classes. With
this design, we can ensure that existing code doesn't impact.
Software entities should be open for extension but closed for modification
That means any class or module should be written in a way that it can be used as is, can be extended, but neve modified
Bad Example in Javascript
var juiceTypes = ['Mango','Apple','Lemon'];
function juiceMaker(type){
if(juiceTypes.indexOf(type)!=-1)
console.log('Here is your juice, Have a nice day');
else
console.log('sorry, Error happned');
}
exports.makeJuice = juiceMaker;
Now if you want to add Another Juice type, you have to edit the module itself, By this way, we are breaking OCP .
Good Example in Javascript
var juiceTypes = [];
function juiceMaker(type){
if(juiceTypes.indexOf(type)!=-1)
console.log('Here is your juice, Have a nice day');
else
console.log('sorry, Error happned');
}
function addType(typeName){
if(juiceTypes.indexOf(typeName)==-1)
juiceTypes.push(typeName);
}
function removeType(typeName){
let index = juiceTypes.indexOf(typeName)
if(index!==-1)
juiceTypes.splice(index,1);
}
exports.makeJuice = juiceMaker;
exports.addType = addType;
exports.removeType = removeType;
Now, you can add new juice types from outside the module without editing the same module.
Let's break down the question in three parts to make it easier to understand the various concepts.
Reasoning Behind Open-Closed Principle
Consider an example in the code below. Different vehicles are serviced in a different manner. So, we have different classes for Bike and Car because the strategy to service a Bike is different from the strategy to service a Car. The Garage class accepts various kinds of vehicles for servicing.
Problem of Rigidity
Observe the code and see how the Garage class shows the signs of rigidity when it comes to introducing a new functionality:
class Bike {
public void service() {
System.out.println("Bike servicing strategy performed.");
}
}
class Car {
public void service() {
System.out.println("Car servicing strategy performed.");
}
}
class Garage {
public void serviceBike(Bike bike) {
bike.service();
}
public void serviceCar(Car car) {
car.service();
}
}
As you may have noticed, whenever some new vehicle like Truck or Bus is to be serviced, the Garage will need to be modified to define some new methods like serviceTruck() and serviceBus(). That means the Garage class must know every possible vehicle like Bike, Car, Bus, Truck and so on. So, it violates the open-closed principle by being open for modification. Also it's not open for extension because to extend the new functionality, we need to modify the class.
Meaning Behind Open-Closed Principle
Abstraction
To solve the problem of rigidity in the code above we can use the open-closed principle. That means we need to make the Garage class dumb by taking away the implementation details of servicing of every vehicle that it knows. In other words we should abstract the implementation details of the servicing strategy for each concrete type like Bike and Car.
To abstract the implementation details of the servicing strategies for various types of vehicles we use an interface called Vehicle and have an abstract method service() in it.
Polymorphism
At the same time, we also want the Garage class to accept many forms of the vehicle, like Bus, Truck and so on, not just Bike and Car. To do that, the open-closed principle uses polymorphism (many forms).
For the Garage class to accept many forms of the Vehicle, we change the signature of its method to service(Vehicle vehicle) { } to accept the interface Vehicle instead of the actual implementation like Bike, Car etc. We also remove the multiple methods from the class as just one method will accept many forms.
interface Vehicle {
void service();
}
class Bike implements Vehicle {
#Override
public void service() {
System.out.println("Bike servicing strategy performed.");
}
}
class Car implements Vehicle {
#Override
public void service() {
System.out.println("Car servicing strategy performed.");
}
}
class Garage {
public void service(Vehicle vehicle) {
vehicle.service();
}
}
Importance of Open-Closed Principle
Closed for modification
As you can see in the code above, now the Garage class has become closed for modification because now it doesn't know about the implementation details of servicing strategies for various types of vehicles and can accept any type of new Vehicle. We just have to extend the new vehicle from the Vehicle interface and send it to the Garage. That's it! We don't need to change any code in the Garage class.
Another entity that's closed for modification is our Vehicle interface.
We don't have to change the interface to extend the functionality of our software.
Open for extension
The Garage class now becomes open for extension in the context that it will support the new types of Vehicle, without the need for modifying.
Our Vehicle interface is open for extension because to introduce any new vehicle, we can extend from the Vehicle interface and provide a new implementation with a strategy for servicing that particular vehicle.
Strategy Design Pattern
Did you notice that I used the word strategy multiple times? That's because this is also an example of the Strategy Design Pattern. We can implement different strategies for servicing different types of Vehicles by extending it. For example, servicing a Truck has a different strategy from the strategy of servicing a Bus. So we implement these strategies inside the different derived classes.
The strategy pattern allows our software to be flexible as the requirements change over time. Whenever the client changes their strategy, just derive a new class for it and provide it to the existing component, no need to change other stuff! The open-closed principle plays an important role in implementing this pattern.
That's it! Hope that helps.
It's the answer to the fragile base class problem, which says that seemingly innocent modifications to base classes may have unintended consequences to inheritors that depended on the previous behavior. So you have to be careful to encapsulate what you don't want relied upon so that the derived classes will obey the contracts defined by the base class. And once inheritors exist, you have to be really careful with what you change in the base class.
Purpose of the Open closed Principle in SOLID Principles is to
reduce the cost of a business change requirement.
reduce testing of existing code.
Open Closed Principle states that we should try not to alter existing
code while adding new functionalities. It basically means that
existing code should be open for extension and closed for
modification(unless there is a bug in existing code). Altering existing code while adding new functionalities requires existing features to be tested again.
Let me explain this by taking AppLogger util class.
Let's say we have a requirement to log application wide errors to a online tool called Firebase. So we create below class and use it in 1000s of places to log API errors, out of memory errors etc.
open class AppLogger {
open fun logError(message: String) {
// reporting error to Firebase
FirebaseAnalytics.logException(message)
}
}
Let's say after sometime, we add Payment Feature to the app and there is a new requirement which states that only for Payment related errors we have to use a new reporting tool called Instabug and also continue reporting errors to Firebase just like before for all features including Payment.
Now we can achieve this by putting an if else condition inside our existing method
fun logError(message: String, origin: String) {
if (origin == "Payment") {
//report to both Firebase and Instabug
FirebaseAnalytics.logException(message)
InstaBug.logException(message)
} else {
// otherwise report only to Firebase
FirebaseAnalytics.logException(message)
}
}
Problem with this approach is that it violates Single Responsibility Principle which states that a method should do only one thing. Another way of putting it is a method should have only one reason to change. With this approach there are two reasons for this method to change (if & else blocks).
A better approach would be to create a new Logger class by inheriting the existing Logger class like below.
class InstaBugLogger : AppLogger() {
override fun logError(message: String) {
super.logError(message) // This uses AppLogger.logError to report to Firebase.
InstaBug.logException(message) //Reporting to Instabug
}
}
Now all we have to do is use InstaBugLogger.logError() in Payment features to log errors to both Instabug and Firebase. This way we reduce/isolate the testing of new error reporting requirement to only Payment feature as code changes are done only in Payment Feature. The rest of the application features need not be tested as there are no code changes done to the existing Logger.
The principle means that it should easy to add new functionality without having to change existing, stable, and tested functionality, saving both time and money.
Often, polymorhism, for instance using interfaces, is a good tool for achieving this.
An additional rule of thumb for conforming to OCP is to make base classes abstract with respect to functionality provided by derived classes. Or as Scott Meyers says 'Make Non-leaf classes abstract'.
This means having unimplemented methods in the base class and only implement these methods in classes which themselves have no sub classes. Then the client of the base class cannot rely on a particular implementation in the base class since there is none.
I just want to emphasize that "Open/Closed", even though being obviously useful in OO programming, is a healthy method to use in all aspects of development. For instance, in my own experience it's a great painkiller to use "Open/Closed" as much as possible when working with plain C.
/Robert
This means that the OO software should be built upon, but not changed intrinsically. This is good because it ensures reliable, predictable performance from the base classes.
I was recently given an additional idea of what this principle entails: that the Open-Closed Principle describes at once a way of writing code, as well as an end-result of writing code in a resilient way.
I like to think of Open/Closed split up in two closely-related parts:
Code that is Open to change can either change its behavior to correctly handle its inputs, or requires minimum modification to provide for new usage scenarios.
Code that is Closed for modification does not require much if any human intervention to handle new usage scenarios. The need simply does not exist.
Thus, code that exhibits Open/Closed behavior (or, if you prefer, fulfills the Open/Closed Principle) requires minimal or no modification in response to usage scenarios beyond what it was originally built for.
As far as implementation is concerned? I find that the commonly-stated interpretation, "Open/Closed refers to code being polymorphic!" to be at best an incomplete statement. Polymorphism in code is one tool to achieve this sort of behavior; Inheritance, Implementation...really, every object-oriented design principle is necessary to write code that is resilient in the way implied by this principle.
In Design principle, SOLID – the "O" in "SOLID" stands for the open/closed principle.
Open Closed principle is a design principle which says that a class, modules and functions should be open for extension but closed for modification.
This principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code (tested code). The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.
Benefit of Open Closed Design Principle:
Application will be more robust because we are not changing already tested class.
Flexible because we can easily accommodate new requirements.
Easy to test and less error prone.
My blog post on this:
http://javaexplorer03.blogspot.in/2016/12/open-closed-design-principle.html