Object Oriented Concepts
In the 1990s, many object-oriented programming languages were developed with the goal of making the programming of complex applications easier. The applications should become more robust, easier to maintain and less error-prone through object-oriented programming (OOP).
Object-oriented programming enables natural modeling, increases the efficiency of the developer by reusing program elements and reduces the complexity of the applications by abstraction and encapsulation.
In this paper we will focus on the basics of object-oriented programming and introduce the most important concepts.
The five concepts of object-oriented programming in Java are:
- abstraction -- differentiation between objects and classes
- encapsulation -- methods and variables together form a class
- reusability -- multiple use of program elements
- relationships -- objects and classes are related to each other
- polymorphism -- object variables can hold instances of derived classes
Abstraction
A major problem in the development of today's applications is their complexity. But to make software development manageable, this complexity must be reduced.
And this is exactly where abstraction helps. Abstraction is used to distinguish between concept and implementation, i.e. there is an object and a construction plan according to which this object is modeled.
This has the advantage that many very similar objects can be created with only one construction plan. An object is thereby a "thing" existing in the application world. The construction plan that is used to model these things is called a class.
It is always useful to create a class (construction plan) when several similar objects are needed, which are not exactly the same, but have many similar characteristics.
Each class must describe at least these four characteristics:
- which characteristics does the object possess?
- how does the object behave?
- how is the object created?
- how is the object operated?
For example, a class could describe the building plan of fire extinguishers and specify exactly which properties fire extinguisher objects have (color, size, content), how fire extinguisher objects behave (what happens when switch A is pressed), how fire extinguisher objects are created (what are the start conditions) and how fire extinguisher objects are operated (which switches can be pressed and when).
If such a class is created, any number of instances of this class (objects) can be created. These objects have many similarities but differ in some details (color, size, ...) and each instance has its own identity.
Encapsulation
A class consists of variables and methods.
If an instance of a class is created, the variables contain the information about the state of the instance (the object). These variables are called instance variables or also attributes, member variables or instance characteristics.
Each instance of a class has its own set of instance variables. These variables can be filled with different values and change during the lifetime of the object.
The methods of a class determine the behavior of the instances. With the help of the methods the contents of the variables can be read and changed. Thus, the methods allow to query the state of the instance and even to change the state.
The methods exist only once in the executable program code. But they work with the data of a specific instance at each call. Which instance this is, is passed as a reference at runtime when the method is called. The method then only accesses the instance variables of this one object.
Encapsulation is the fact that classes consist of variables and methods.
This encapsulation greatly reduces the complexity of operating an object. In order to operate an object, one does not need to know the inner structure, but only the corresponding method.
Reusability
Another very important concept of object-oriented programming is the possibility to reuse program elements.
The reusability is promoted by the two already presented concepts abstraction and encapsulation. Thus objects can be reused very simply. The developer must know only the interfaces and can operate thereby the objects. The developer does not have to worry about the complex details of the code and data structures.
A very well-known example of reusability is the Collection class, which makes it very easy to manage objects in a collection.
Although the Collection class has a very complex structure, it can be used very comfortably via its simple interface.
Reusability makes Java programming more efficient and reduces the number of programming errors significantly.
Relationships
In Java there are 3 basic types of relations, which form objects and classes with each other.
These are:
- generalization and specialization ("is-a" relation)
- aggregation and composition ("part-of" relationship)
- associations (use relationships)
Generalization and Specialization
The "is-a" relationship occurs between two classes, which have an inheritance relationship to each other.
The base class (parent class) inherits its characteristics to the class derived from it. The derived class is not completely redefined, but inherits all characteristics of the base class and new additional characteristics are added to it.
It is said that class B is an A (B "is-a" A) and thus a specialization of class A. Conversely, the base class A is a generalization of the derived class B.
Since inheritances can be multi-level, it is possible that a derived class itself serves as a base class for further classes. Due to the multi-level nature of inheritance, an inheritance hierarchy is formed, which can be represented as a tree structure. These derivation trees are displayed as graphs.
The base classes are placed above the derived classes. The classes are connected with arrows, whereby the arrow direction runs from the derived class to the base class.
Tree structure of the inheritance hierarchy in Java using the example of living beings
The class living being is the base class of all other classes, i.e. all classes inherit their properties. The living being class has exactly one property, in which the age of a living being is stored.
The class mammal is derived from the living being class, thus a specialization of it. It inherits the characteristic Age and adds the property NumberLegs.
The classes human and sheep are derived from the mammal class. Both inherit the characteristics Age and NumberLegs, but have their own individual additional characteristics.
Aggregation and Composition
The "part-of" relationship describes what an object is composed of.
An object can hold other objects. The captured objects can be seen as the individual parts of the main object.
If an object is part of another object, it is in a "part-of" relationship with the main object. For example, a human being has two legs, the legs are in this case part of the human being ("part-of").
If the recorded objects are existential to the main object, this is called a composition. If the captured objects are merely optional, this is called an aggregation.
Composition is the strict form of aggregation, because there is an existential dependency.
Part-of" relationships are implemented in Java by instance variables, which can take up objects. If the object does not exist in an aggregation, the null object is assigned to the corresponding instance variable.
If an object is included, then an instance variable is used for it. If several objects of the same data type are included, an array instance variable of the required data type is used.
Association
In Java, usage relationships specify that an object temporarily uses an instance of a certain class to perform a certain operation.
Usage relationships always occur when objects (instances of classes) are only used temporarily. This is the case with local object variables and method arguments. Such objects only exist within a method, i.e. temporarily.
This kind of relations is also called associations.
Polymorphism
In Java it is possible that an object variable can contain objects that are of a different data type.
This concept is called Polymorphismus (variety).
The object variable is thereby of the data type of the basis class A. It cannot take up any arbitrary object, but only objects, which are instances of a class derived from the basis class A.
In the concrete case this means, that an object variable of the type living being can contain objects of the type living being (instances of the class living being) as well as objects of the type mammal, human, sheep, bird, fish, pike and carp (instances of the classes derived from the base class living being).
The flexibility is provided by the Java compiler, which ensures that only the properties of the class of the object variable can be accessed. Because these properties are at least present in every assignable object due to the inheritance hierarchy.
Polymorphism is only allowed from the general class (main class) towards the specialized class (derived class).
An object variable of the type of the derived class cannot include an object of the base class because the base class object does not have all the properties of the derived class. However, these properties could be accessed via the object variable, which would lead to undefined program behavior.
LivingBeing GeneralLB; // Object variable of the type of the base class living being
// Object variable of the type living being gets an instance of the class living being assigned
generalLB = new LivingBeing(); // allowed, the standard case
humanLB = new Human();
sheep sheepLB = new Sheep();
// Object variable of the type living being gets an instance of the class human
generalLB = humanLB; // polymorphism - allowed, because of specialization
// Object variable of the type living creature gets an instance of the class sheep
generalLB = sheepLB; // Polymorphism - allowed, because of specialization
// Object variable of the type sheep gets an instance of the class living being assigned
sheepLB = generalLB; // not allowed, because of generalization
// Object variable of the type sheep gets an instance of the class human assigned
sheepLB = humanLB; // not allowed, because same hierarchy level
The concept of the Polymorphismus makes the so-called Late Binding possible, whereby methods can be overlaid. A method is implemented already in the basis class, but in the derived classes by a more special method implementation overlaid. At runtime it is then decided which method implementation is executed.
For example, the class Living Being could have a method getMovementType. This method returns the locomotion type of the living being object. Each derived class could implement its own version of the method getMovementManner, which would then be executed at runtime instead of the general method getMovementManner of the base class.
If a method has not been re-implemented in the derived class, i.e. there is no overlay, the runtime system simply uses the method implementation from the parent class that is closest to its own class.