Object-Oriented Programming (OOP) is a programming paradigm using "objects" to design applications.
An object is a thing which has its own identity.
An object contains both state and behavior. State of an object is the
current data and behavior is implemented as methods. An object in an OO
language can be easily compared to a real world object. Consider a car. A
car has some properties like model, fuel type etc which are the state
(or properties) of that object. Similarly it will also have functions.
Object-Oriented Programming (OOP) has certain
important features like Encapsulation, Polymorphism, Inheritance and
Abstraction. These features are also referred to as OOPS concepts.
ENCAPSULATION
Encapsulate in plain English means to enclose or be enclosed in or as if in a capsule.
A capsule is an unit. In languages such as C and C++, we can have
global variables outside classes. But in Java, everything is within a
class or interface. So everything is within some unit. Encapsulation in Java is the process of wrapping up of data (properties) and behavior (methods) of an object into a single unit; and the unit here is a Class (or interface).
Encapsulation enables data hiding,
in which, an object hide its attributes behind its operations. An
object hides its attributes from the outside world by making it private,
and then exposes them through setters and getters. A setter is a method
used to change the value of an attribute and a getter is a method used
to get the value of an attribute. There is also a standard naming
convention for getters and setters, but Java compiler won't complain
even otherwise.
Example: Consider a variable name and its getter and setter:
private String name;public String getName() {return name;}public void setName(String name) {this.name=name;}
Since this is a standard convention, many IDEs like eclipse will generate it for you.
Without encapsulation, the code would become
dependent on attributes. It would be then difficult to change the
internal representation of the object in future. Consider the example of
a linked list’s getsize method. We might be now using a variable named
size that is updated on every insert / delete operation. Later we might
decide to traverse the list and find size every time someone ask for
size. But if some code was directly accessing the size variable, we
would have to change all those code for this change. However if we were
accessing the size variable through a getsize method, other code can
still call that method and we can do our changes in that method.
INHERITANCE
Inheritance allows us to specify that a class gets
some of its characteristics from a parent class and then adds unique
features of its own.
For example consider a Vehicle parent class and a
child class Car. Vehicle class will have all common properties and
functionalities for all vehicles in common and Car will inherit those
common properties from the Vehicle class and then add those properties
which are specific to a car. Here, Vehicle is known as base class,
parent class, or superclass. Car is known as derived class, Child class
or subclass.
Java supports single inheritance (single parent)
in a class context referred to as implementation inheritance. Java also
supports multiple inheritance (multiple parents) limited to an interface
content, which is also referred to as interface inheritance.
POLYMORPHISM
The ability to change form is known as
polymorphism. Java supports different kinds of polymorphism like
oveloading, overriding, parametric etc.
Overloading
The same method name (method overloading) or
operator symbol (operator overloading) can be used in different
contents. In method overloading, multiple methods having same name can
appear in a class, but with different signature. And based on the number
and type of arguments we provide while calling the method, the correct
method will be called.
Java doesn't allow operator overloading yet + is
overloaded for class String. The ‘+’ operator can be used for addition
as well as string concatenation.
Overriding (or subtype polymorphism)
Overriding is defining a method in a subclass with
the same name and type signature as a method in its superclass and when
this subclass instance appears in the superclass context like Parent p =
new Child() and when we execute an overridden method as p.myMethod(),
the subtype’s version of that method is executed. Here, the actual
method called will depend on the object at runtime, not the reference
type.
Consider an example class Shape with a draw()
method. It can have subclasses Circle and Square. An object of Circle or
Square can be assigned to a Shape reference as Shape s = new Circle();.
While executing draw() on the Shape reference, it will draw a Circle or
Square based on the actual object assigned to it at runtime.
In java, only instance methods are overridden.
Static methods, static variables and instance variables are just
re-declared (hiding parent method) in the child class, but not
overridden. Here, the actual method called depend on the reference type
and not the object at runtime. Hence by calling a method using a parent
reference executes the parent class versions of that method.
In java 5 and above, we can confirm whether we are
doing valid override by using the @Override annotation above the
subclass's method. Compiler will throw error when @Override is applied
on static methods, static variables or instance variables as only
instance methods are overriden.
Parametric polymorphism through generics
Within a class declaration, a field name can
associate with different types and a method name can associate with
different parameter and return types. Java supports parametric
polymorphism via generics.
An example is a list which can accept the type of data it contains through generics.
List<String> list = new ArrayList<String>();
Coercion (or implicit conversion)
An operation can serve multiple types through implicit type conversion.
For example, in case of a division operation, if
one operand is an integer and other is a floating point, the compiler
coerces (implicitly converts) the integer to a floating point value, to
prevent a type error.
Another example is passing a subclass object
reference to a method’s superclass parameter type. The compiler coerces
the subclass type to the superclass type, to restrict operation to those
of the superclass.
Note: Many text books consider only oveloading, overriding and parametric as types of polymorphism.
ABSTRACTION
In plain English, abstract means a concept or idea
not associated with any specific instance and does not have a concrete
existence. Abstraction in Object Oriented Programming refers to the
ability to make a class abstract. Abstraction captures only those
details about an object that are relevant to the current perspective.
Abstraction tries to reduce and factor out details so that the
programmer can focus on a few concepts at a time. Java provides
interfaces and abstract classes for describing abstract types. An interface is a contract or specification without any implementation. An interface can't have behavior or state. An abstract class
is a class that cannot be instantiated. All other functionality of the
class still exists. Abstract classes can have state and can be used to
provide a skeletal implementation.
Coupling vs Cohesion
Coupling and cohesion are two important concepts in the OO design and hence we will briefly discuss it here.
Coupling is the degree to which one class knows
about another class. If the knowledge is only through exposed interfaces
(data hiding), it is called loosely coupled. If the knowledge is more
like accessing data members directly, it is called tightly coupled. We
should try to make our code as loosely coupled as possible. Even though
you make some change in a class adhering strictly to the class's API,
tight coupling can make other classes that use this class not working
properly after the change.
The term cohesion is used to indicate the degree
to which a class has a single, well-focused purpose. The more focused a
class is, the higher its cohesiveness, which is a good thing. The key
benefit of high cohesion is that such classes are typically much easier
to maintain than classes with low cohesion. Another benefit of high
cohesion is that classes with a well-focused purpose tend to be more
reusable than other classes.
Main concept: Object-oriented programming is all about creating a society of cooperating, active "agents" (objects) that, working together, accomplish the desired task.
|
Classes and objects
|
An object contains data (instance variables) representing its state, and instance methods, which are the things it can do.
A class may also contain its own data (class variables) and class methods. The keyword
static denotes such data and methods.An object "knows" what class it belongs to, and can use class data and class methods, but a class does not "know" about its objects.
Classes form a hierarchy (tree), with
Object at
the root. Every class, except Object, has one and only one immediate
superclass, but that class has its own immediate superclass, and so on all
the way up to Object at the root, and all of these are superclasses
of the class. The keyword extends denotes the immediate
superclass.A class contains one or more constructors for making new objects of that class. If (and only if) the programmer does not write a constructor, Java provides a default constructor with no arguments. The default constructor sets instance variables as follows: numeric types are set to zero,
boolean
variables are set to false, char variables are set
to '\0', and object variables are set to null.The purpose of a constructor is to create an object in a valid state. No other work should be done in a constructor.
When a constructor executes, the very first thing it does is call the constructor for its superclass. You can write this constructor call explicitly, with
super(...);,
or you can let it implicitly call the default constructor.A constructor for a class can call another constructor for the same class by putting
this(...); as the first thing in the constructor.
This allows you to avoid repeating code.Objects are declared just like primitive values, with the syntax
ClassName objectName;
but are not defined (allocated space and given a value)
until you create one by calling the constructor with the keyword new.Classes inherit all the data and all the methods of their superclasses, but do not inherit constructors.
You can assign an object of a class to a variable (that is,
variable
= object) declared to be of that class or any of its superclasses
(thus, you can assign any object to a variable of type Object).
If you have an object in a more general variable or expression (for example,
a String value in an Object variable), you can cast
it to the correct type with the syntax (type)variable
or (type)(expression).Casting an object to a more general type is called upcasting, and is always legal. Casting an object to a more specific type is called downcasting, and Java inserts a run-time check to ensure that the cast is legal. Casting does not affect what the object is, it only changes what fields and methods are available on the object at the position the cast occurs.
A class that is declared as
final may not be extended by
subclasses.The
instanceof operator tests whether its left operand
(an object) is an instance of its right operand (a class or interface). The
result will be true if the right operand is the class or any superclass
of the object. Well-designed programs have very little need for the instanceof
operator. A Java source file may contain only one
public class, though
it may contain additional non-public classes. The name of the file must be the
same as the name of the class, but with the .java extension.Classes should be as self-contained and independent as it is reasonable to make them. The interface (the fields and methods it makes available outside the class) should be kept small.
An object is responsible for keeping itself in a valid state. Therefore, it should limit write access to essential fields.
|
Access
|
There are three dimensions to accessing names: namespaces, scope, and access modifiers.
Java uses six different namespaces: package names, type names, field (variable) names, method names, local variable names (including parameters), and labels. Identical names of different types do not conflict; for example, a method may be named the same as a local variable. However, it's best to avoid reusing names in this manner.
The scope of a name is the part of a class in which it can be seen.
- A variable declared anywhere in a class can be seen everywhere in a class.
- The scope of a method's formal parameters is the entire method.
- The scope of a variable declared in a block (indicated by braces,
{ }) extends from the declaration to the closing brace. A method body is always a block. - The scope of a variable declared in the initialization part of a
forloop is the entireforloop.
static)
can be used anywhere within the class.Instance variables and instance methods can be used anywhere within the class except in static methods.
Within an instance method, the keyword
this refers to the
object currently executing the method.When an instance variable and a formal parameter have the same name, the name refers to the formal parameter; prefix the name with
this.
to refer to the instance variable.To refer to an instance name in a different object, use the syntax
otherObject.name.
To refer to a class (static) name in a different class, use the syntax
OtherClass.name.You can refer to a name (class or instance) in another class if and only if you have access privileges. Possible access privileges are:
public: You can access it from anywhere.protected: You can access it from any other class in the same directory (folder), or from any subclass.- package (default) : You can access it from any other class in the same directory.
private: You cannot access it from outside the class. Surprisingly, private variables and methods can be accessed by other objects in the same class.
- You can use the fully-qualified name, for instance
java.awt.Color.RED - You can import a specific class or (with
*) all classes in a given package, then use the name with or without the package qualification, for instanceColor.RED.
|
Methods
|
All executable statements must be in methods. (Exception: "initialization blocks," not covered here.)
A method has a signature consisting of its name and the number and types of its parameters (also called "arguments"). The parameters in the method declaration are its formal parameters.
A method has a return type, which is not part of its signature. If the return type is other than
void, then the method must return
a value of the specified type.A method may have local variables (also called method variables). These follow the scope rules, and are never available anywhere outside the method. The concepts
static, public, protected,
package, and private do not apply to local variables. Local variables
have undefined values upon method entry. Formal parameters are a kind of local
variable, but have initial values as supplied by the corresponding actual parameters.Every method must have a signature that is unique within its class. Methods in other classes (even superclasses and subclasses) may have the same signature.
An instance method is executed by sending a message to its object. The message consists of: a reference to the object (typically its name), a dot, the name of the method, and zero or more actual parameters enclosed in parentheses. The object will respond by executing the corresponding method in the actual class of the object, which may be different from the type of the variable holding the object.
A class method is executed by sending a message to the class. The message consists of: the name of the class, a dot, the name of the method, and zero or more actual parameters enclosed in parentheses. The class will respond by executing the corresponding static method in that class.
When a message is sent, and before the method executes, the values of the actual parameters are copied into the corresponding formal parameters. Then the method body executes. Then the return value replaces the message, and all local names are forgotten.
|
Polymorphism
|
The two kinds of polymorphism are overloading and overriding.
Overloading occurs when a class declares two or more methods with the same name but different signatures. When a message is sent to an object or class with overloaded methods, the method with the best matching signature is the one that is used ("invoked").
- If the message and the method have a different number of parameters, no match is possible.
- If the message and the method have exactly the same types of parameters, that is the best possible match.
- Messages with specific actual parameter types can invoke methods with more
general formal parameter types. For example if the formal parameter type is
Object, an actual parameter of typeStringis acceptable (since aStringvalue can be assigned to anObjectvariable). If the formal parameter is typedouble, an actual parameter of typeintcan be used (for similar reasons). - If there is no clear best match, Java reports a syntax error.
- Overriding is commonly used to make methods more specific.
- When a method
nameis overridden, you can still invoke the superclass' method (from inside the class) with the syntaxsuper.name(parameters). - From outside the class, you can cast an object to its superclass and then
invoke the method, with the syntax
((Superclass)object).name(parameters). - Restrictions:
- Although the return type is not part of the signature, an overriding method must have the same return type as the method it overrides.
- The overriding method cannot be more private than the method it overides
(
public>protected> package >private). - The overriding method may not throw any exception types in addition to those thrown by the method it overrides (although it may throw fewer exception types).
- Shadowing should be avoided.
- When shadowing does happen, you can access the superclass name by either
the syntax
super.nameor by casting the object to its superclass, with the syntax((Superclass)object).name.
|
Interfaces and abstract
classes
|
The purpose of interfaces and abstract methods is to ensure that any classes derived from them will share the same set of methods.
An abstract method is a method that is declared but not defined. It is declared with the keyword
abstract, and has a header
like any other method, but ends with a semicolon instead of a method body.An abstract class is one that contains one or more abstract methods; it must itself be declared with the
abstract keyword. A
class may be declared abstract even if it does not contain any abstract methods.
A non-abstract class is sometimes called a concrete class.An abstract class cannot be instantiated; that is, no objects of that class can be created. Instead, you can create subclasses that define (in the usual way) the inherited abstract methods, and these subclasses can be instantiated.
An interface is declared with the keyword
interface
instead of the keyword class. An interface may contain only
public abstract methods and definitions of constants (that is, final
variables). The keywords public and abstract
before each method are optional.A class may extend only one other class, but it may implement any number of interfaces. The syntax is:
class Class extends
Superclass implements Interface1, Interface2, ....
When a class extends an interface, it may implement (define) some or all of
the inherited abstract methods. A class must itself be declared abstract
if it inherits abstract methods that it does not define.A variable may be declared to have a type that is an abstract class or an interface; any object whose type implements or extends the variable's type may be assigned to that variable. The
instanceof operator
may take a class, abstract class, or interface as its right operand.|
Inner classes
|
A member class is defined at the top level of the class, along with fields and methods. It may have the same access modifiers as variables (
public,
protected, package, static, final),
and is accessed in much the same way as variables of that class.A static member class is defined like a member class, but with the keyword
static. Despite its position inside another class, a static member
class is actually an "outer" class--it has no special access to names
in its containing class. To refer to the static inner class from a class outside
the containing class, use the syntax OuterClassName.InnerClassName.
A static member class may contain static fields and methods.A local inner class is defined within a method, and the usual scope rules apply to it. It is only accessible within that method, therefore access restrictions (
public, protected, package)
do not apply. However, because objects (and their methods) created from this
class may persist after the method returns, a local inner class may not refer
to parameters or non-final local variables of the method.An anonymous inner class is one that is declared and used to create one object (typically as a parameter to a method), all within a single statement. The anonymous inner class may either extend a class or implement an interface; the syntax is the same for both:
new Super(parameters){methods},
where Super is the name of the extended class or
implemented interface, parameters are the parameters
to the constructor for that class or interface (usually just ()),
and methods override any inherited methods.The keyword
static may not be used within any inner class except
a static member class.