Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Design Patterns and Best Practices in Java

You're reading from   Design Patterns and Best Practices in Java A comprehensive guide to building smart and reusable code in Java

Arrow left icon
Product type Paperback
Published in Jun 2018
Publisher Packt
ISBN-13 9781786463593
Length 280 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (4):
Arrow left icon
Kamalmeet Singh Kamalmeet Singh
Author Profile Icon Kamalmeet Singh
Kamalmeet Singh
Lucian-Paul Torje Lucian-Paul Torje
Author Profile Icon Lucian-Paul Torje
Lucian-Paul Torje
Sumith Kumar Puri Sumith Kumar Puri
Author Profile Icon Sumith Kumar Puri
Sumith Kumar Puri
Adrian Ianculescu Adrian Ianculescu
Author Profile Icon Adrian Ianculescu
Adrian Ianculescu
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. From Object-Oriented to Functional Programming 2. Creational Patterns FREE CHAPTER 3. Behavioral Patterns 4. Structural Patterns 5. Functional Patterns 6. Let's Get Reactive 7. Reactive Design Patterns 8. Trends in Application Architecture 9. Best Practices in Java 10. Other Books You May Enjoy

Object-oriented paradigm

The object-oriented paradigm is often associated with imperative programming, but, in practice, both functional and object-oriented paradigms can coexist. Java is living proof that supports this collaboration.

In the following section, we will briefly highlight the main object-oriented concepts as they are implemented in the Java language.

Objects and classes

Objects are the main elements of an object-oriented programming (OOP) language. An object holds both the state and the behavior.

If we think of classes as a template, objects are the implementation of the template. For example, if human is a class that defines the behavior and properties that a human being can have, you and I are objects of this human class, as we have fulfilled all the requirements of being a human. Or, if we think of car as a class, a particular Honda Civic car will be an object of this class. It will fulfill all the properties and behaviors that a car has, such as it has an engine, a steering wheel, headlights, and so on, and it has behaviors of moving forward, moving backward, and so on. We can see how the object-oriented paradigm can relate to the real world. Almost everything in the real world can be thought of in terms of classes and objects, hence it makes OOP effortless and popular.

Object-oriented programming is based on four fundamental principles:

  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism (subtyping polymorphism).

Encapsulation

Encapsulation basically means the binding of attributes and behaviors. The idea is to keep the properties and behavior of an object in one place, so that it is easy to maintain and extend. Encapsulation also provides a mechanism to hide unnecessary details from the user. In Java, we can provide access specifiers to methods and attributes to manage what is visible to a user of the class, and what is hidden.

Encapsulation is one of the fundamental principles of object-oriented languages. It helps in the decoupling of different modules. Decoupled modules can be developed and maintained more or less independently. The technique through which decoupled modules/classes/code are changed internally without affecting their external exposed behavior is called code refactoring.

Abstraction

Abstraction is closely related to encapsulation, and, to some extent, it overlaps with it. Briefly, abstraction provides a mechanism that exposes what an object does and hides how the object does what it's supposed to do.

A real-world example of abstraction is a car. In order to drive a car, we don't really need to know what the car has under the hood, but we need to know the data and behavior it exposes to us. The data is exposed on the car's dashboard, and the behavior is represented by the controls we can use to drive a car.

Inheritance

Inheritance is the ability to base an object or class on another one. There is a parent or base class, which provides the top-level behavior for an entity. Every subclass entity or child class that fulfills the criteria to be a part of the parent class can inherit from the parent class and add additional behavior as required.

Let's take a real-world example. If we think of a Vehicle as a parent class, we know a Vehicle can have certain properties and behaviors. For example, it has an engine, doors, and so on, and behavior-wise it can move. Now all entities that fulfill these criteria—for example, Car, Truck, Bike, and so on—can inherit from Vehicle and add on top of given properties and behavior. In other words, we can say that a Car is a type of Vehicle.

Let's see how this will look as code; we will first create a base class named Vehicle. The class has a single constructor, which accepts a String (the vehicle name):

public class Vehicle 
{
private Stringname;
public Vehicle(Stringname)
{
this.name=name;
}
}

Now we can create a Car class with a constructor. The Car class is derived from the Vehicle class, so it inherits and can access all the members and methods declared as protected or public in the base class:

public class Car extends Vehicle
{
public Car(String name)
{
super(name)
}
}

Polymorphism

In broad terms, polymorphism gives us an option to use the same interface for entities of different types. There are two major types of polymorphism, compile time and runtime. Say you have a Shape class that has two area methods. One returns the area of a circle and it accepts single integer; that is, the radius is input and it returns the area. Another method calculates the area of a rectangle and takes two inputs, length and breadth. The compiler can decide, based on the number of arguments in the call, which area method is to be called. This is the compile-time type of polymorphism.

There is a group of techies who consider only runtime polymorphism as real polymorphism. Runtime polymorphism, also sometimes known as subtyping polymorphism, comes into play when a subclass inherits a superclass and overrides its methods. In this case, the compiler cannot decide whether the subclass implementation or superclass implementation will be finally executed, and hence a decision is taken at runtime.

To elaborate, let's take our previous example and add a new method to the vehicle type to print the type and name of the object:

public String toString()
{
return "Vehicle:"+name;
}

We override the same method in the derived Car class:

public String toString()
{
return "Car:"+name;
}

Now we can see subtyping polymorphism in action. We create one Vehicle object and one Car object. We assign each object to a Vehicle variable type because a Car is also a Vehicle. Then we invoke the toString method for each of the objects. For vehicle1, which is an instance of the Vehicle class, it will invoke the Vehicle.toString() class. For vehicle2, which is an instance of the Car class, the toString method of the Car class will be invoked:

Vehicle vehicle1 = new Vehicle("A Vehicle");
Vehicle vehicle2 = new Car("A Car")
System.out.println(vehicle1.toString());
System.out.println(vehicle2.toString());
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image