What is Object-Oriented Programming (OOP)?
If you use classes and objects in your programs, but
neither inheritance nor polymorphism, many authors refer
to this as "object-based" programming, but insist that
it not be called "object-oriented" programming unless
you employ inheritance and polymorphism as well.
The Three Pillars of OOP
Benefits and Goals of OOP
Natural OOP uses the terminology of
the problem, not the terminology of a computer.
Reliable Modular construction puts
knowledge and responsibility where they belong,
and allows each component to be tested and validated
Reusable Well designed class objects
can form reusable components (but of
course this is not guaranteed).
Maintainable OOP permits software
components to change or even be replaced completely
in a way that should be transparent to the rest of
Extendable OOP permits easy addition of
new functionality, as the user's needs change over
Timely OOP permits quicker development
times by allowing parallel development of independent
classes by independent developers.
Pitfalls of OOP
Thinking only of the programming language
That is, not paying enough attention to everything
else that's involved, and then blaming "the technology"
when things go wrong.
Thinking of OOP as a cure-all Using OPP does
not guarantee success. There is never any substitute for
good judgment. Planning, designing and careful coding are
always necessary, whatever your approach and however
sophisticated your tools may be.
Fearing to re-use code That is, always wanting
to start from scratch.
Selfish programming That is, not wanting to
share the code you create.
More Details on the Three Pillars
Encapsulation in this context means "putting together
the things that should be together, in particular attributes
and operations (data and methods).
The fundamental underlying notion is that of "abstraction",
and in particular the Abstract Data Type (ADT).
An ADT is usually implemented by something called a "class".
Data (attributes) and operations (behaviors, and also called
functions, or methods) are combined in the class definition.
Both are also referred to as "members" of the class.
A program consists of a collection of "objects" of various
classes that make things happen by communicating with each
other by "sending messages"; i.e., one object can send a message
to another object by asking that object to perform one of its
methods (Java syntax: object.method(parameter_list))
The Principle of Information Hiding (David Parnas) insists on
a "contract" between the implementor and the user. This establishes
a "division of responsibility" in which the implementor should be
told only what is necessary for implementing the class, and the
client should be told only what is necessary to use the class.
In each case it's a question of "minding one's own business".
This may be enforced, or at least encouraged by "access control"
(public, private, protected) of class members. In this context,
don't confuse "inaccessible" with "invisible".
Inheritance is a hierarchical relationship in which the
members of one class are all passed down to any class
that descends from (extends) that class, directly or
indirectly. It is in this sense that we appear to be
"getting something for nothing".
This is just one of a number of different relationships
that may exist between different classes.
Thus, inheritance is a mechanism for defining a new class
based on the definition of a pre-existing class, in such
a way that all the members of the "old" class (superclass,
or parent class, or base class) are present in the "new"
class (subclass, or child class, or derived class), and an
object of the new class may be substituted anywhere for an
object of the old class. This is the Principle of
Represents the "is-a" relationship
A Tiger is-a Mammal.
A Whale is-a Mammal.
But, is it true that a Penguin
And is it true that a
It is in trying to answer questions like these
that the Principle of Substitutability comes in handy.
An inherited class may simply use the members that
are already there, may add new members, or may
"override" members that pre-existed in the parent
or ancestor class (by giving those "overridden"
members new definitions).
An inheritance hierarchy is a tree-like
mapping of the relationships that form between
classes as the result of inheritance. (C++ allows
multiple inheritance, as in "a SingingWaiter
is-a Singer and a SingingWaiter is-a Waiter", but this
is not permitted in Java.)
Inheritance hierarchies should develop naturally
as you program, and not be "forced" in any way.
There are different "kinds" of inheritance:
Specialization In this form of
inheritance the derived class adds more
functionality and/or overrides some of the
existing functionality. It makes good use of
polymorphism, and is probably the most frequently
used form of inheritance. (See ThreePillars.java.)
Extension This is a particular form
of specialization in which more functionality
is added but none of the existing functionality
Realization of a Specification
In this form an
"abstract class" or "interface" (both of which
contain unimplemented methods) is used as the
base to realize a concept merely
"specified" in that base.
Combination This occurs when we want
to use more than one base class ("multiple
inheritance" in the sense of C++ does not exist
in Java). The alternative is to "inherit from",
or "extend", a single base class, and
simultaneously "implement" one or more "interfaces".
Other ways to use inheritance, which should perhaps
be avoided, or at least considered very carefully
- Construction (Composition is often a better
- Limitation (This destroys substitutability.
It is easy to do this in C++ with "private inheritance",
but not so easy in Java.)
Bad use of inheritance is sometimes called the
Frankenstein's Monster of OOP.
Polymorphism may be regarded as the knock-out punch of OOP,
if encapsulation and inheritance are its one-two punches.
Polymorphism literally means "many forms".
Here is an everyday example: We use the word
"open" in may ways (many forms), since we open
doors, open windows, open envelopes, open
packages, open bank accounts, open our minds,
open our hearts, open our eyes, and open our
In OOP, polymorphism refers to the fact that a
single name (like open, above) can be used to
represent or select different code at differnt
times, depending on the situation, and according
to some automatic mechanism. So, for example,
the method call object.DoIt() can mean
different things at different times in the same
There are different kinds of polymorphism:
Pure polymorphism This is also called
inclusion polymorphism), and means
that a single function is applied to a variety
of types (Example: the valueOf
method in class String)
Overriding In this case a method further
up a class hierarchy is redefined in a subclass,
giving either total replacement of the redefined
method, or just a refinement of that method.
Deferred methods These are methods that
are specified but not implemented in an abstract
class or an interface, and in one sense this may
be considered a generalization of overriding.
Overloading This is also called
ad hoc polymorphism), and in this
case a number of different functions (code
bodies) all have the same name, but are
distinguished by having different parameter
lists (parametric overloading, often
aided in C++ by the use of default parameters,
which are not available in Java) Note, however,
that overloading does not necessarily imply
similar actions by the code. (Example:
In a card game program, draw might
mean to draw a card on the screen in one class,
but to choose a card from the deck in another class.)