Related
I have a class Game and now I need to add players (IPlayer) to the game. And I'm thinking about two scenarios:
First approach
IPlayer AddPlayer()
In this scenario the caller does not have to worry about implementation of IPlayer. He get just an interface and cannot tamper with the object. The Game knows implementation details and can manage player's state, for example add points:
interface IPlayer
{
int Points { get; }
}
class Player : IPlayer
{
...
void AddPoints(int points);
}
Second approach
void AddPlayer(IPlayer player)
In this approach it's the caller who is responsible for delivering an object that meets the interface. Thus know sthe details.
I'm wondering: Is any of those approaches apparently better/worse?
Just a comment about my point of view:
My goal is to have clear API. And I think that the first approach is better. When I give a user my library then I give him just interface. All the details are maintained inside. (Similarly I could give an access to IGame that under the hood is an instance of Game)
I would strongly recommend using a "composition" approach as Unity does. Don't create classes/interfaces modeled around specific game entities. Have a GameObject class instead, exposing a collection of Components.
Each Component would add some features and behavior to the owning GameObject, like position, physics, stats and so on.
One GameObject instance can act as some sort of "game controller", spawning entities and keeping track of the score (or whatever rules your game has).
I am reading Head First Object Oriented Design to get a better understanding of OOP concepts.
Polymorphism is explained as:
Airplane plane = new Airplane();
Airplane plane = new Jet();
Airplane plane = new Rocket();
You can write code that works on the superclass, like an airplane, but will work with any of the subclasses. :- * Hmmm.. ..I got this one.*.
It further explains:
-> So how does polymorphism makes code flexible?
Well, if you need new functionality, you could write a new subclass of
AirPlane. But since your code uses the superclass, your new class will work
without any changes to the rest of your code.
Now I am not getting it. I need to create a sublass of an airplane. For example: I create a class, Randomflyer. To use it I will have to create its object. So I will use:
Airplane plane = new Randomflyer();
I am not getting it. Even I would have created an object of a subclasses directly. Still I don't see a need to change my code anywhere when I will add a new subclass. How does using a superclass save me from making extra changes to the rest of my code?
Say you have the following (simplified):
Airplane plane = new MyAirplane();
Then you do all sorts of things with it:
List<Airplane> formation = ...
// superclass is important especially if working with collections
formation.add(plane);
// ...
plane.flyStraight();
plane.crashTest();
// ... insert some other thousand lines of code that use plane
Thing is. When you suddenly decide to change your plane to
Airplane plane = new PterdodactylSuperJet();
all your other code I wrote above will just work (differently, of course) because the other code relies on the interface (read:public methods) provided by the general Airplane class, and not from the actual implementation you provide at the beginning. In this way, you can pass on different implementations without altering your other code.
If you hadn't used an Airplane superclass and just written MyAirplane and PterdodactylSuperJet in the sense that you replace
MyAriplane plane = new MyAirplane();
with
PterdodactylSuperJet plane = new PterdodactylSuperJet();
then you have a point: the rest of your code may still work. But that just happens to work, because you wrote the same interface (public methods) in both classes, on purpose. Should you (or some other dev) change the interface in one class, moving back and forth between airplane classes will render your code unusable.
Edit
By on purpose I mean that you specifically implement methods with the same signatures in both MyAirplane and PterodactylSuperJet in order for your code to run correctly with both. If you or someone else change the interface of one class, your flexibility is broken.
Example. Say you don't have the Airplane superclass and another unsuspecting dev modifies the method
public void flyStraight()
in MyAirplane to
public void flyStraight (int speed)
and assume your plane variable is of type MyAirplane. Then the big code would need some modifications; assume that's needed anyway. Thing is, if you move back to a PterodactylSuperJet (e.g. to test it, compare it, a plethora of reasons), your code won't run. Whygodwhy. Because you need to provide PterodactylSuperJet with the method flyStraight(int speed) you didn't write. You can do that, you can repair, that's alright.
That's an easy scenario. But what if
This problem bites you in the ass a year after the innocent modification? You might even forget why you did that in the first place.
Not one, but a ton of modificatios had occurred that you can't keep track of? Even if you can keep track, you need to get the new class up to speed. Almost never easy and definitely never pleasant.
Instead of two plane classes you have a hundred?
Any linear (or not) combination of the above?
If you had written an Airplane superclass and made each subclass override its relevant methods, then by changing flyStraight() to flyStraight(int) in Airplane you would be compelled to adapt all subclasses accordingly, thus keeping consistency. Flexibility will therefore not be altered.
End edit
That's why a superclass stays as some kind of "daddy" in the sense that if someone modifies its interface, all subclasses will follow, hence your code will be more flexible.
A very simple use-case to demonstrate the benefit of polymorphism is batch processing of a list of objects without really bothering about its type (i.e. delegating this responsibility to each concrete type). This helps performing abstract operations consistently on a collection of objects.
Let's say you want to implement a simulated flight program, where you would want to fly each and every type of plane that's present in your list. You simply call
for (AirPlane p : airPlanes) {
p.fly();
}
Each plane knows how to fly itself and you don't need to bother about the type of the planes while making this call. This uniformity in the behaviour of the objects is what polymorphism gives you.
Other people have more fully addressed your questions about polymorphism in general, but I want to respond to one specific piece:
I am not getting it, even I would have create an object of subclasses
directly.
This is actually a big deal, and people go to a lot of effort to avoid doing this. If you crack open something like the Gang of Four, there are a bunch of patterns dedicated to avoiding just this issue.
The main approach is called the Factory pattern. That looks something like this:
AirplaneFactory factory = new AirplaneFactory();
Airplane planeOne = factory.buildAirplane();
Airplane planeTwo = factory.buildJet();
Airplane planeThree = factory.buildRocket();
This gives you more flexibility by abstracting away the instantiation of the object. You might imagine a situation like this: your company starts off primarily building Jets, so your factory has a buildDefault() method that looks like:
public Airplane buildDefault() {
return new Jet();
}
One day, your boss comes up to you and tells you that the business has changed. What people really want these days are Rockets -- Jets are a thing of the past.
Without the AirplaneFactory, you'd have to go through your code and replace possibly dozens of calls to new Jet() with new Rocket(). With the Factory pattern, you can just make a change like:
public Airplane buildDefault() {
return new Rocket();
}
and so the scope of the change is dramatically reduced. And since you've been coding to the interface Airplane rather than the concrete type Jet or Rocket, this is the only change you need to make.
Suppose you have methods in your Controller class of Planes like
parkPlane(Airplane plane)
and
servicePlane(Airplane plane)
implemented in your program. It will not BREAK your code.
I mean, it need not to change as long as it accepts arguments as AirPlane.
Because it will accept any Airplane despite of actual type, flyer, highflyr, fighter, etc.
Also, in a collection:
List<Airplane> plane; // Will take all your planes.
The following example will clear your understanding.
interface Airplane{
parkPlane();
servicePlane();
}
Now your have a fighter plane that implements it, so
public class Fighter implements Airplane {
public void parkPlane(){
// Specific implementations for fighter plane to park
}
public void servicePlane(){
// Specific implementatoins for fighter plane to service.
}
}
The same thing for HighFlyer and other clasess:
public class HighFlyer implements Airplane {
public void parkPlane(){
// Specific implementations for HighFlyer plane to park
}
public void servicePlane(){
// specific implementatoins for HighFlyer plane to service.
}
}
Now think your controller classes using AirPlane several times,
Suppose your Controller class is AirPort like below,
public Class AirPort{
AirPlane plane;
public AirPlane getAirPlane() {
return airPlane;
}
public void setAirPlane(AirPlane airPlane) {
this.airPlane = airPlane;
}
}
here magic comes as Polymorphism makes your code more flexible because,
you may make your new AirPlane type instances as many as you want and you are not changing
code of AirPort class.
you can set AirPlane instance as you like (Thats called dependency Intection too)..
JumboJetPlane // implementing AirPlane interface.
AirBus // implementing AirPlane interface.
Now think of If you create new type of plane, or you remove any type of Plane does it make difference to your AirPort?
No, Because we can say the The AirPort class refers the AirPlane polymorphically.
As far as I understand, the advantage is that, for example, in a airplane combat game, you have to update all airplanes' positions at every loop, but you have several different airplanes. Let's say you have:
MiG-21
Waco 10
Mitsubishi Zero
Eclipse 500
Mirage
You don't want to have to update their movements and positions in separate like this:
Mig21 mig = new Mig21();
mig.move();
Waco waco = new Waco();
waco.move();
Mitsubishi mit = new Mitsubishi();
mit.move();
...
You want to have a superclass that can take any of this subclasses (Airplane) and update all in a loop:
airplaneList.append(new Mig21());
airplaneList.append(new Waco());
airplaneList.append(new Mitsubishi());
...
for(Airplane airplane : airplanesList)
airplane.move()
This makes your code a lot simpler.
You are completely correct that sub-classes are only useful to those who instantiate them. This was summed up well by Rich Hickey:
...any new class is itself an island; unusable by any existing code written by anyone, anywhere. So consider throwing the baby out with the bath water.
It is still possible to use an object which has been instantiated somewhere else. As a trivial example of this, any method which accepts an argument of type "Object" will probably be given an instance of a sub-class.
There is another problem though, which is much more subtle. In general a sub-class (like Jet) will not work in place of a parent class (like Airplane). Assuming that sub-classes are interchangable with parent classes is the cause of a huge number of bugs.
This property of interchangability is known as the Liskov Substitution Principle, and was originally formulated as:
Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.
In the context of your example, T is the Airplane class, S is the Jet class, x are the Airplane instances and y are the Jet instances.
The "properties" q are the the results of the instances' methods, the contents of their properties, the results of passing them to other operators or methods, etc. We can think of "provable" as meaning "observable"; ie. it doesn't matter if two objects are implemented differently, if there is no difference in their results. Likewise it doesn't matter if two objects will behave differently after an infinite loop, since that code can never be reached.
Defining Jet as a sub-class of Airplane is a trivial matter of syntax: Jet's declaration must contain the extends Airplane tokens and there mustn't be a final token in the declaration of Airplane. It is trivial for the compiler to check that objects obey the rules of sub-classing. However, this doesn't tell us whether Jet is a sub-type of Airplane; ie. whether a Jet can be used in place of an Airplane. Java will allow it, but that doesn't mean it will work.
One way we can make Jet a sub-type of Airplane is to have Jet be an empty class; all of its behaviour comes from Airplane. However, even this trivial solution is problematic: an Airplane and a trivial Jet will behave differently when passed to the instanceof operator. Hence we need to inspect all of the code which uses Airplane to make sure that there are no instanceof calls. Of course, this goes completely against the ideas of encapsulation and modularity; there's no way we can inspect code which may not even exist yet!
Normally we want to sub-class in order to do something differently to the superclass. In this case, we have to make sure that none of these differences is observable to any code using Airplane. This is even more difficult than syntactically checking for instanceof; we need to know what all of that code does.
That's impossible due to Rice's Theorem, hence there's no way to check sub-typing automatically, and hence the amount of bugs it causes.
For these reasons, many see sub-class polymorphism as an anti-pattern. There are other forms of polymorphism which don't suffer these problems though, for example "parameteric polymorphism" (referred to as "generics" in Java).
Liskov Substitution Principle
Comparison between sub-classing and sub-typing
Parameteric polymorphism
Arguments against sub-classing
Rice's theorem
One good example of when polymorphism is useful:
Let us say you have abstract class Animal, which defines methods and such common to all animals, such as makeNoise()
You then could extend it with subclasses such as Dog, Cat, Tiger.
Each of these animals overrides the methods of the abstract class, such as makeNoise(), to make these behaviors specific to their class. This is good because obiously each animal makes a different noise.
Here is one example where polymorphism is a great thing: collections.
Lets say I have an ArrayList<Animal> animals, and it is full of several different animals.
Polymorphism makes this code possible:
for(Animal a: animals)
{
a.makeNoise();
}
Because we know that each subclass has a makeNoise() method, we can trust that this will cause each animal object to call their specific version of makeNoise()
(e.g. the dog barks, the cat meows, the cow moos, all without you ever even having to worry about which animal does what.)
Another advantage is apparent when working with a team on a project. Let's say another developer added several new animals without ever telling you, and you have a collection of animals which now has some of these new animal types (which you dont even know exist!). You can still call the makeNoise() method (or any other method in the animal superclass) and trust that each type of animal will know what to do.
The nice thing about this animal superclass is that you can a extend a superclass and make as many new animal types as you want, without changing ANYTHING in the superclass, or breaking any code.
Remember the golden rule of polymorphism. You can use a subclass anywhere a superclass type object is expected.
For example:
Animal animal = new Dog;
It takes a while to learn to think polymorphically, but once you learn your code will improve a lot.
Polymorphism stems from inheritance. The whole idea is that you have a general base class and more specific derived classes. You can then write code that works with the base class... and polymorphims makes your code not only work with the base class, but all derived classes.
If you decide to have your super class have a method, say getPlaneEngineType(), and you make a new child class "Jet which inherits from Plane". Plane jet = new Jet() will/can still access the superclass's getPlaneEngineType. While you could still write your own getJetEngineType() to basically override the superclass's method with a super call, This means you can write code that will work with ANY "plane", not just with Plane or Jet or BigFlyer.
I don't think that's a good example, since it appears to confuse ontology and polymorphism.
You have to ask yourself, what aspect of the behaviour of a 'Jet' is different from an 'Airplane' that would justify complicating the software to model it with a different sub-type? The book's preview cuts off after one page into the example, but there doesn't seem any rationale to the design. Always ask yourself if there is a difference in behaviour rather than just adding classes to categorise things - usually that's better done with a property value or composing strategies than with sub-classes.
An example (simplified from a major project I lead in the early noughties) would be that an Aeroplane is final but has various properties of abstract types, one of which is the engine. There are various ways of calculating the thrust and fuel use of an engine - for fast jets bi-cubic interpolation table of values of thrust and fuel rate against Mach and throttle (and pressure and humidity sometimes), for Rockets the table method but does not require compensation for stalling the air at the engine intake; for props a simpler parametrised 'bootstrap' equation can be used. So you would have three classes of AbstractAeroEngine - JetEngine, RocketEngine and BootstrapEngine which would have implementations of methods which returned thrust and fuel use rate given a throttle setting and the current Mach number. (you should almost never sub-type a non-abstract type)
Note that the differences between the types of AbstractAeroEngine, although related to the different real world engines, are entirely differences in the how the software calculates the engine's thrust and fuel use - you are not constructing an ontology of classes which describe a view of the real world, but specialising the operations performed in the software to suit specific use cases.
How does using a superclass save me from making extra changes to rest of my code?
As all your engine calculations are polymorphic, it means that when you create an aeroplane, you can bolt on whatever engine thrust calculation suits it. If you find you have to cater for another method of calculating the thrust (as we did, several times) then you can add another sub-type of AeroEngine - as long as the implementation it supplies provides the trust and fuel rate, then the rest of the system doesn't care about the internal differences - the AeroPlane class will still ask its engine for the thrust. The aeroplane only cares that it has an engine which it can use the same way as any other engine, only the creation code has to know the type of the engine to bolt onto it, and the implementation of ScramJetEngine only cares about supersonic jet calculations - the parts of AeroPlane which calculate lift and drag, and the strategy for flying it don't have to change.
Polymorphism is powerful given that when there's a need to change a behavior you can change it by overriding a method.
Your superclass inherits its properties and behaviors to your subclasses extended by it. Thus it is safe to implicitly cast an object whose type is also from its superclass. Those common methods to your subclasses make them useful to implement an API. With that, polymorphism gives you the ability to extend a functionality of your code.
Polymorphism gains properties and all behaviors and interfaces of the super class. So is the behavior of a plane really the same as a jet?
I'm having an issue in OO design where I end up with duplicate code in 2 different classes. Here's what's going on:
In this example, I want to detect collision between game objects.
I have a base CollisionObject that holds common methods (such as checkForCollisionWith) and CollisionObjectBox, CollisionObjectCircle, CollisionObjectPolygon that extend the base class.
This part of design seems ok, but here's what's troubling me: calling
aCircle checkForCollisionWith: aBox
will perform a circle vs box collision check inside Circle subclass. In reverse,
aBox checkForCollisionWith: aCircle
will perform box vs circle collision check inside Box subclass.
Issue here is that Circle vs Box collision code is duplicate, since it's in both Box and Circle classes. Is there a way to avoid this, or am I approaching this problem the wrong way? For now, I'm leaning towards having a helper class with all the duplicate code and call it from the aCircle and aBox objects to avoid duplicates. I'm curious if there's more elegant OO solution to this, though.
What you want is referred to as multi dispatch.
Multiple dispatch or multimethods is the feature of some object-oriented programming languages in which a function or method can be dynamically dispatched based on the run time (dynamic) type of more than one of its arguments.
This can be emulated in the mainline OOP languages, or you can use it directly if you use Common Lisp.
The Java example in the Wikipedia article even deals with your exact problem, collision detection.
Here's the fake in our "modern" languages:
abstract class CollisionObject {
public abstract Collision CheckForCollisionWith(CollisionObject other);
}
class Box : CollisionObject {
public override Collision CheckForCollisionWith(CollisionObject other) {
if (other is Sphere) {
return Collision.BetweenBoxSphere(this, (Sphere)other);
}
}
}
class Sphere : CollisionObject {
public override Collision CheckForCollisionWith(CollisionObject other) {
if (other is Box) {
return Collision.BetweenBoxSphere((Box)other, this);
}
}
}
class Collision {
public static Collision BetweenBoxSphere(Box b, Sphere s) { ... }
}
Here's it in Common Lisp:
(defmethod check-for-collision-with ((x box) (y sphere))
(box-sphere-collision x y))
(defmethod check-for-collision-with ((x sphere) (y box))
(box-sphere-collision y x))
(defun box-sphere-collision (box sphere)
...)
This is a typical pitfall in OO development. I once also tried to solve collisions in this manner - only to fail miserably.
This is a question of ownership. Do Box class really owns the collision logic with circle? Why not the other way round? Result is code duplicity or delegating collision code from circle to Box. Both are not clean. Double dispatch doesn't solve this - same problem with ownership...
So you are right - you need third party functions/methods which solves particular collisions and a mechanism that selects the right function for two objects that are colliding (here double dispatch can be used, but if number of collision primitives is limited then probably 2D array of functors is faster solution with less code).
I had the same problem (working in Objective C), and a workaround I found for this is to define an external function to solve the collision when I already know types for both objects.
For example, if I have Rectangle and Circle, both implementing a protocol (kind of interface for this language) Shape..
#protocol Shape
-(BOOL) intersects:(id<Shape>) anotherShape;
-(BOOL) intersectsWithCircle:(Circle*) aCircle;
-(BOOL) intersectsWithRectangle:(Rectangle*) aRectangle;
#end
define intersectsWithCircle for Rectangle, and intersectsWithRectangle for Circle like this
-(BOOL) intersectsWithCircle:(Circle*) aCircle
{
return CircleAndRectangleCollision(aCircle, self);
}
and ...
-(BOOL) intersectsWithRectangle:(Rectangle*) aRectangle
{
return CircleAndRectangleCollision(self, aRectangle);
}
Of course it doesn't attack the coupling problem of Double Dispatch, but at least it avoids code duplication
You should use checkForCollisionWith: aCollisionObject and since all your objects are extending CollisionObject you can put all common logic there.
Alternatively you could use the delegation design pattern to share common logic between different classes.
You don't say what language you are using, so I presume it is something like Java or C#.
This is a situation where multimethods would be an ideal solution, but most languages do not support them. The usual way to emulate them is with some variation of the visitor pattern - see any good book on design patterns.
Alternatively have a separate CollisionDetection class that checks for collisions between pairs of objects, and if two objects collide then it calls the appropriate methods on the objects, e.g. bomb.explode() and player.die(). The class could have a big lookup table with each object type along the rows and columns, and the entries giving the methods to call on both objects.
Perhaps you could have a collision object which contains the methods for testing for different types of collisions. The methods could return other objects which contain the collision point and other necessary information.
First option: Make the collision directional. For example, if the box is stationary, it doesn't check its own collisions with anything else; but the moving circle checks collision with the box (and other stationary objects). This is unintuitive because all our lives we're taught "equal and opposite reactions". Pitfall: moving objects would duplicate collisions with other moving objects.
Second option: Give every object a unique ID number. In the collision checking method, only check the collision if the first parameter/object has a lower ID than the second parameter.
Say the box has id=2 and circle has id=5. Then, "box collides with circle" would be executed, since box.id < circle.id; but then when the circle is checking collisions, "circle collides with box" will just return immediately without checking the collision, because the collision would have already been checked.
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
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
My relative is studying programming and has a hard time understanding classes. He has trouble understanding for example that you need to instantiate it, that methods cannot access variables in other methods and if you change a variable in one instance of a class it doesn't change for other instances.
I've tried to use analogies like a class definition is like a blueprint of a house. And instances are houses made from that blueprint.
How do you explain classes and OO in general?
Seriously use Animals, it works great. And that's what nailed the concept for me years ago. Just found this C# code. It seems good
// Assembly: Common Classes
// Namespace: CommonClasses
public interface IAnimal
{
string Name
{
get;
}
string Talk();
}
// Assembly: Animals
// Namespace: Animals
public class AnimalBase
{
private string _name;
AnimalBase(string name)
{
_name = name;
}
public string Name
{
get
{
return _name;
}
}
}
// Assembly: Animals
// Namespace: Animals
public class Cat : AnimalBase, IAnimal
{
public Cat(String name) :
base(name)
{
}
public string Talk() {
return "Meowww!";
}
}
// Assembly: Animals
// Namespace: Animals
public class Dog : AnimalBase, IAnimal
{
public Dog(string name) :
base(name)
{
}
public string Talk() {
return "Arf! Arf!";
}
}
// Assembly: Program
// Namespace: Program
// References and Uses Assemblies: Common Classes, Animals
public class TestAnimals
{
// prints the following:
//
// Missy: Meowww!
// Mr. Bojangles: Meowww!
// Lassie: Arf! Arf!
//
public static void Main(String[] args)
{
List<IAnimal> animals = new List<IAnimal>();
animals.Add(new Cat("Missy"));
animals.Add(new Cat("Mr. Bojangles"));
animals.Add(new Dog("Lassie"));
foreach(IAnimal animal in animals)
{
Console.WriteLine(animal.Name + ": " + animal.Talk());
}
}
}
And once he's got this nailed, you challenge him to define Bird (fly), and then Penguin (fly!?)
The best way I got it through to my wife (a chartered accountant) is as follows.
In 'regular' programming you have data (things that are manipulated) and code (things that manipulate) and they're separate. Sometimes you get mixed up because a certain piece of code tries to manipulate the wrong thing.
In my wife's case, I said a invoice arrived (which involves no physical money changing hands) and accidentally updated a bank balance, something she immediately saw as potential fraud (she used to do forensic accounting, everything is potential fraud to her, including most of my share trades :-).
You could just as easily say that a piece of code meant to wash a floor with a huge mop decided to do it with your toothbrush.
With OO programming, the manipulators and manipulatees are inextricably entwined. You don't apply the floor washing process to the floor, instead you command the floor to wash itself. It knows how to do this because the code is part of the object, not something external to it.
In the accounting case above, I think we ended up having the chart of accounts as the object and we told it to apply a invoice to itself. Since it understood the process, it knew which accounts were allowed to be updated (creditors liability account and an expense account if I remember correctly).
Anyway, that's irrelevant and I'm just meandering now. What I'm saying is to express it in terms your target audience will understand. I suppose that's the secret of most teaching.
Like all old farts, I'd like to answer this with a story from my own life.
I started programming basic on a VIC-20. Not knowing anything else, I though this was how all computers were programmed. I thought it was a bit hard to keep track of which variable names I had used and which were still free, (scope problem). I also thought it was hard to divide my program into repeatable chunks using gosub-return and setting and reading the variables that these would use, (lack of methods).
Then I got into Turbo C over MS-DOS. Now I could create my own methods and functions! I was no longer stuck with the old finite set of commands in basic. I felt like I was creating a new language for every program I wrote. C gave me more expressive power.
C++ was the first object oriented language I heard about. The big moment for me was when I understood that I could create my own data types, and even overload the operators. Again, it felt like I could create my own language containing both new functions and data types, complete with operators.
That's how I would sell OO to a new programmer. Explain that it gives expressive power because they can define their own data types. I always thought encapsulation was a better selling point than inheritance.
I assume the target knows how to use graphical user interfaces. I found the best way is to describe OOP with stuff that they are really used for. Say
Class
A Window is a class. It has methods like
Show a window
Enable a window
Set the window's title
A Window has attributes. That is data associated with it. It is encapsulated into the class, together with the functions that operate on them
A Window has dimensions. Width and height.
A Window has possibly a parent window, and possibly children.
A Window has a title
Object
There are many windows. Each particular window is an object of the class Window. A Parent window containing 10 windows makes 11 Window objects.
Deriveration
A Button is a Window. It has dimensions has a parent window and has a title, the label of a button. It's a special kind of a window. When you ask for a window object, someone can give you a Button. A Button can add functions and data that are specific for a button:
A Button has a state. It can be in a pressed state, and unpressed state.
A Button can be the default button in a Window.
While you are explaining OO with animals, do not forget to illustrate the "is-a" relationship with Stinger missiles-armed kangaroos ;-)
The kangaroos scattered, as predicted, and the Americans nodded appreciatively . . . and then did a double-take as the kangaroos reappeared from behind a hill and launched a barrage of stinger missiles at the hapless helicopter. (Apparently the programmers had forgotten the remove "that" part of the infantry coding).
The lesson? Objects are defined with certain attributes, and any new object defined in terms of the old one inherits all the attributes. The embarrassed programmers had learned to be careful when reusing object-oriented code, and the Yanks left with the utmost respect for the Australian wildlife.
Read the Java tutorials for some good ideas and real world examples.
How about "each molding is built using a mold", or "each model is built using a template", and so "each object is built using a class" ?
Note that it works for class-oriented OOP (which is what you want), but not for prototype-oriented OOP.
As for explaining OOP to a programmer, I'd add examples illustrating:
Separating state from behavior
Most of the time, an instance describe a state, and a class describe a behavior.
Delegation
An instance delegates its behavior to its class, and the class in turn can delegate its behavior to its superclasses (or mixins or traits)
Polymorphism
If class A inherits from class B, an instance of A can be used anywhere an instance of class B can be used.
Messages & methods
A message (or generic function, or virtual function) is like a question. Most of the time, several classes can answer to this question.
A corresponding method is a possible answer to the question, that resides in a class.
When sending a message to an instance, the instance looks up for a corresponding method in its class. If found, it calls it (with the instance bound to 'self' or 'this'. Otherwise, it looks for a corresponding method in its mixins, traits, or superclasses, and calls it.
If they're old enough to have ever filled out a tax form, show them a 1040EZ and explain that an instance of a class is like a filled-out form: each blank is a member variable of the object, and the form also includes instructions for what to do with the member variables, and those instructions are the member functions of the object. A class itself is like a master copy of the form, from which you can print off an endless number of blank forms to fill out.
One thing that I would counsel to AVOID in trying to communicate the concepts of OO to new programmers is using only examples where objects (in the OO sense) represent real-world physical objects. This will actually make students more confused when they encounter objects used to represent non-physical objects (such as a color scheme, or most of the behavioral patterns in "Design Patterns") or objects used just as a useful way to store related functions and related data in the same place (think Java's java.lang.Math for an example.)
Believe it or not, sports!
I've had success in teaching and mentoring by talking about the way that e.g. a play for a football team is described in terms of how the various positions (Center, Quarterback, Runningback, etc.) interact to accomplish a particular goal. In one version, the positions correspond to classes, and specific persons (Tony Romo, Johnny Unitas, etc.) are instances of the class -- individuals who exhibit the same behaviors as defined by the positions.
The second version of this metaphor is to explain that the positions may be interfaces (in the Java sense) rather than classes. An interface really represents a role fulfilled by any object that implements the methods of the interface. And it's perfectly reasonable for an object (via its class, in Java) to implement multiple interfaces, just as it is possible for a talented individual to play more than one position on a sports team.
Finally, the play is like a pattern, in that it describes how a set of roles interact to accomplish some specific goal.
An object is a black box, which you can't see through. Public methods are buttons on them. Protected methods are buttons hidden on the bottom, private methods are dip switches inside.
Let's see a washer as an object. We don't know how it works. We don't care if it's powered by natural gas, diesel, electricity, or plutonium. However, the mechanism and internal structure will vary greatly depending on the energy source like a combustion engine is needed for some. We don't care as long as if we push a "Wash" button, it washes our clothes.
Let's turn the washer not Object-oriented. Expose all the buttons by arranging them on the top. Customers can now turbo-charge the engine by tweaking some dip switches. Make the chassis transparent. Now, you can see your energy-saving washing machine is actually hybrid-powered. There are some monkeys in it. You free them into the wild, and the machine eats up your utility bill like a gas-guzzler.
Object-oriented programming is one technique of raising the level of abstraction by means of which the programmer communicates with the computer: from the level of flipping individual bits on and off, from the level of punching holes in paper cards, from the level of extraordinarily complex sequences of basic instruction codes, from the level of less complicated definitions of reusable templates for blocks of data and reusable blocks of code (structs and procedures), to the level of transcribing the concepts in the programmer's mind into code, so that what goes on inside the computer comes to resemble, for the programmer, what goes on outside the computer in the world of physical objects, intangible assets, and cause-and-effect.
the best book i've ever on object-oriented programming is Betrand's "Object-Oriented Software Construction" - if you really want to get the basics, there is no way around it.
I explain that procedural program is built around the "verbs" of the system, the things you want the system to do, whereas object-oriented programming is build about the "nouns," the things in the system, and what they are capable of, and that for many people this allows for a more straightforward mapping from the problem domain to software.
For the example, I use cars -- "Honda Accord" is a class, whereas the vehicle sitting in the parking lot is an object, an instance of a Honda Accord. A Honda Accord is a sedan, which is a car, which is an automobile, which is a motorized vehicle, which is a mode of transportation, etc. I cannot do anything with a car until I have a physical car to work with -- it doesn't help me that the idea of a Honda Accord exists.
It also helps for discussing interfaces and polymorphism -- the gas pedal means accelerate, regardless what the car does behind the scenes to make that happen. There are "private" parts of the car that I as user do not have access to -- I cannot directly apply an individual brake.
Since the issue is to explain to a new programmer and not to a mother or a wife, I would go right straight to the point. OO is about three main concepts:
Inheritance: a dog is an animal, parent-child, is-a relationship test, etc.
Encapsulation: public-private (protected), information hiding, internal underlying details are not important to the users of the class, protect users from future changes in the implementation.
Polymorphism: run-time binding, late binding, method that gets invoked depends on the type of the object and not the reference or pointer to the object.
Also, depending on how much the new programmer has been doing a procedural language, I would need to help him/her unlearn that the functions or procedures are no longer central.
Games are good.
There are gameobjects, from this walls, enemies and players inherit.
The gameobjects should be renderable have collision-logic etc. The enemies have ai-logic while the player is keyboard controlled.
Some UI-elements are also good, there are buttons, inputboxes etc that all inherit from some baseobject that has code for managing mouse-events etc.
I don't like the animal-example because i've never seen a "real" program that has ever had to use of animals in that way. It will only make people use inheritance all over the place and you will end up with cubes inheriting from rectangles that inherit from lines (why does so many books insist on using this as example? ).
OOP is a higher level of abstraction, a programmer can't really come to grasp it unless he has a good understanding of the normal (read: procedural) way of programming, and he must be able to write some programs that do something useful.
For me it took a series of several lectures by one of my university profs, where he discussed many theoretical aspects of programming, he tried to convince us that programming is about manipulating data, and that this data is a representation of the "state(s)" of the program, and some other abstract stuff that I forgot now! But the point is, it's hard to understand OOP without some theoretical abstract discussion first, and this discussion wouldn't make any sense to a person who hadn't had experience writing some real code.
After the theoretical discussion, you give an example of a moderately complex program, written in procedural style, and slowly convert it, step by step, into object oriented style. After the concrete example, you should go back to the theoretical discussion and just summarize the main points, directly relate the theoretical constructs to the concrete example, e.g you can talk about how the name, age, and salary of an employee represent his state.