An essential idea behind object-oriented programming is that solutions rise from the interactions between objects which are created from classes.
An object in object-oriented programming is an independent unit that has a state, which can be modified by using the methods that the object provides.
Objects are used in cooperation; each has its own area of responsibility.
Every Java class extends the class Object, which means that every class we create has at its disposal all the methods defined in the Object class.
If we want to change how these methods are defined in Object function, they must be overridden by defining a new implementation for them in the newly created class. The objects we create receive the methods equals
and hashCode
, among others, from the Object class.
Each class can directly extend only one class.
However, a class indirectly inherits all the properties of the classes it extends. So the ArrayList
class derives from the class AbstractList
, and indirectly derives from the classes AbstractCollection
and Object
. So ArrayList
has at its disposal all the variables and methods of the classes AbstractList
, AbstractCollection
, and Object
.
You use the keyword extends
to inherit the properties of a class. The class that receives the properties is called the subclass, and the class whose properties are inherited is called the superclass.
public class Part {
private String identifier;
private String manufacturer;
private String description;
public Part(String identifier, String manufacturer, String description) {
this.identifier = identifier;
this.manufacturer = manufacturer;
this.description = description;
}
public String getIdentifier() {
return identifier;
}
public String getDescription() {
return description;
}
public String getManufacturer() {
return manufacturer;
}
}
public class Engine {
private String engineType;
private String identifier;
private String manufacturer;
private String description;
public Engine(String engineType, String identifier, String manufacturer, String description) {
this.engineType = engineType;
this.identifier = identifier;
this.manufacturer = manufacturer;
this.description = description;
}
public String getEngineType() {
return engineType;
}
public String getIdentifier() {
return identifier;
}
public String getDescription() {
return description;
}
public String getManufacturer() {
return manufacturer;
}
}
We notice a significant amount of overlap between the contents of Engine
and Part
. It can confidently be said the Engine
is a special case of Part
.
The Engine is a Part, but it also has properties that a Part does not have, which in this case means the engine type.
public class Engine extends Part {
private String engineType;
public Engine(String engineType, String identifier, String manufacturer, String description) {
super(identifier, manufacturer, description);
this.engineType = engineType;
}
public String getEngineType() {
return engineType;
}
}
On its first line we use the keyword super
to call the constructor of the superclass. The call super(identifier, manufacturer, description)
calls the constructor public Part(String identifier, String manufacturer, String description)
which is defined in the class Part.
The super
call bears some resemblance to the this
call in a constructor; this
is used to call a constructor of this class, while super
is used to call a constructor of the superclass.
If a constructor uses the constructor of the superclass by calling super
in it, the super
call must be on the first line of the constructor. This is similar to the case with calling this
(must also be the first line of the constructor).
If a method or variable has the access modifier private
, it is visible only to the internal methods of that class.
Subclasses will not see it, and a subclass has no direct means to access it.
The programmer cannot access the variables of the superclass that have been defined with the access modifier private.