What is object-oriented programming
Object-oriented programming is a computer programming methodology with the focus on objects that have state and behavior. Object-oriented languages care about more about operations on objects than the logic to operate on the objects. Classes define the blue prints for the objects that will be initialized from them. The operation logic is stored inside class methods. Classes make use of other classes in their operations. Determining which class keeps what kind of behavior and the relationships between classes is an essential component of object-oriented design. Java is a high level, object-oriented oriented programming language.
Object-oriented programming languages have three features in common:
1- Inheritance: Allows deriving a new class from a base class.
2- Encapsulation: Binds methods and fields of a class together in a single unit. This makes it possible to allow access to the fields with restricted visibility only through wrapper methods which provides safety for those fields.
3- Polymorphism: Allowing an object to take many forms. For example, a parent object reference may point to an instance of a child object or an instance of the parent object itself.
In this chapter, we will talk about the some basic Java concepts related to object-oriented programming. This will be the basis to understanding how principles of object-oriented programming are implemented in Java in the coming chapters.
What’s an abstract method?
Abstract methods can only be declared; they cannot have bodies. Java allows defining abstract methods only in interfaces and abstract classes. A method with a body is called a concrete method.
An abstract method is defined as follows.
void printEmployeeNumber();
What’s an interface?
An interface is a contract for defining a class. Interfaces cannot have methods with bodies; they just declare abstract methods. The behavior that is declared in an interface gets its body in the class that uses the interface as a template. This is done using the implements keyword. The class using the interface as its template is called the implementing class or the implementation of the interface.
Now let’s defining an interface with an example.
public interface GeometricShape {
double getArea();
double getPerimeter();
}
All geometric shapes have an area and a perimeter. The calculation of these two attributes is common behavior for all geometrical objects.So it makes sense to put the methods to calculate area and parameter in an interface which can be used as a template for all the geometric shapes. That means, the classes implementing GeometricShape interface are meant to provide bodies for getArea() and getPerimeter() methods. Both methods are declared without an access modifier.
Now, let’s define a Rectangle class and a Circle class both of which implements GeometricShape interface.
public Rectangle implements GeometricShape {
public double width;
public double height;
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
}
public Circle implements GeometricShape {
double radius;
public double getArea() {
return 3.14 * radius * radius;
}
public double getPerimeter() {
return 2 * 3.14 * radius;
}
}
Here, we have two implementations for the GeometricShape interface: Rectangle and Circle. Both of these classes implement the GeometricShape interface using the implements keyword and they provide implementations for both of the methods declared in the interface. Clearly, Circle and Rectangle are different geometric shapes and they implement the interface methods differently. But, because they implement the same GeometricShape interface that represents geometric shapes, they both are geometric shapes. So, a geometric shape may refer to both a Rectangle and a Circle legally.
Java defines the following rules for interfaces:
- All the methods in an interface are inherently public and abstract. public and abstract keywords are the only modifiers allowed to precede a method declared in an interface but omitting any of these does not cause a problem. The following are the same when defined in an interface:
double getArea();
public double getArea();
public abstract double getArea();
Therefore, interfaces cannot declare static methods, either.
- Interface can define only public static fields. public and static keywords are the only modifiers allowed to precede a method declared in an interface but omitting any of these does not cause a problem. The following are the same when defined in an interface:
String DEFAULT_WIDTH = 5;
public String DEFAULT_WIDTH = 5;
public static String DEFAULT_WIDTH = 5;
Here are the rules for implementing an interface:
- The implementing class is required to provide implementations for all the methods of the interface unless it is an abstract class.
- The implementing class cannot restrict the visibility of a method. Therefore all the method implementations in the implementing class are required to be public.
- The implementing class automatically has access to the fields defined in the interface as if they were defined inside the implementing class.
Now, let’s add a field to the GeometricShape interface.
public interface GeometricShape {
String description = “Represents a geometric shape”;
double getArea();
double getPerimeter();
}
Because it is defined in an interface, description is inherently a public and static field. Now, let’s add a main method to the Rectangle implementation of GeometricShape interface.
public Rectangle implements GeometricShape {
public double width;
public double height;
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
public static void main(String [] args) {
Rectangle rectangle = new Rectangle();
rectangle.width = 2;
rectangle.height = 5;
System.out.println(description);
System.out.println(“area: “ + getArea();
}
}
Here, description field can be used in the main method of the implementing class without going through an object instance because it is a public static field. The output would be:
Represents a geometric shape.
Area: 10
Abstract Classes
Abstract classes contain at least one abstract method and they are declared with the abstract modifier. Abstract classes cannot be initialized but they can contain methods with bodies in addition to the abstract methods.
Classes that do not declare abstract methods are called concrete classes. Concrete classes do not have the abstract keyword in their class definitions.
A standard way to declare an abstract class is declared as follows:
<access modifier> abstract <class name> {
<abstract methods>
<concrete methods>
}
Here is a comparison of concrete classes and an abstract classes:
- An abstract class is declared with the abstract modifier while a concrete class is not.
- An abstract class is required to have at least one abstract method while concrete methods cannot have abstract methods.
- Abstract methods of abstract classes are meant to be used as templates for concrete classes that descend from them. This is done using the extends keyword.
- Abstract classes cannot be initialized but they can define constructor methods. These constructor methods can be used by the classes that are derived from abstract classes.
- An abstract class can declare all the other components that a concrete class declaration has. In other words, just like a concrete class, an abstract class can have instance variables, static variables, static and instance methods vs.
- A concrete class that derives itself from an abstract class is required to implement all the abstract methods defined in the abstract class. Java allows deriving another abstract class from an abstract class. In such cases, the derived abstract class is not required to implement the abstract methods defined in the original abstract class but it may if it wants to.
- Abstract classes can implement interfaces but unlike a concrete class they are not required to implement the methods declared in the interface. However, they may if they want to.
Now let’s define an abstract class with both abstract and concrete methods.
public abstract class Bird {
public String breed;
public Bird(String breed) {
this.breed = breed;
}
public void fly() {
System.out.println(“Bird is flying.”);
}
abstract void printHabitatInfo();
}
The Bird class is abstract, therefore it has to define at least one abstract method. printHabitatInfo() method of the Bird class is abstract. In addition to this, Bird class defines a constructor method, a concrete method and an instance variable. Because they are declared public, they can be accessed by the classes derived from this abstract class.
What is extends keyword?
As we have seen at the beginning of this chapter, Java is an object oriented language and it supports inheritance. As part of the inheritance feature, in Java, extends keyword is used to derive a new class from a base class. In this relationship, the base class is called the parent class or super class while the class that extends the base class is called a child class or a subclass.
Now, let’s derive a subclass from the Bird class that we defined.
public class GoldFinch extends Bird {
public void printHabitatInfo() {
System.out.println(“Most of North America, Europe and Asia.”);
}
public static void main(String [] args) {
GoldFinch goldFinch = new Bird(“Goldfinch”);
goldFinch.fly();
goldFinch.printHabitatInfo();
}
}
Here, GoldFinch is a subclass of Bird. It inherits its parent’s all public and protected methods and fields; in this case, breed instance variable and fly() method. It also provides the implementation for the abstract printHabitatInfo() method.
Inside the main method, we initialize a new GoldFinch object using Bird’s constructor. As we said before, a subclass has access to the public methods of its parent class. The Bird class’ constructor is public and therefore visible to the GoldFinch class. The GoldFinch class inherits the constructor, too, when it extends the Bird class and so this constructor can be used to initialize a GoldFinch object.
Abstract Classes implementing Interfaces
Just like concrete classes, abstract classes can implement interfaces, too. But abstract classes are not required to provide implementations for the methods declared in the interface. If an abstract class implements an interface and a concrete class extends that abstract class, then the concrete class needs to implement all the methods of the interface that are not implemented by the abstract class and all the abstract methods of the abstract class.
A concrete class is required to provide implementations for all the methods it inherits that were declared with the abstract keyword and but not implemented by one of its parent classes.
Now, let’s define an interface Animal that is supposed to serve as a template to define some basic behavior that applies to all animals. Every animal has a color and an animal can be aquatic or not.
public interface Animal {
String getColor();
boolean isAquatic();
}
Now, let’s define an abstract class Fish that implements this interface. We know that all fish are aquatic. However, some of the fish live in freshwater while some live in saltwater.
public abstract class Fish implements Animal {
abstract boolean livesInFreshWater();
}
Now, let’s define a specific fish that lives in the ocean.
public class BluefinTuna extends Fish implements Animal
We see that BluefinTuna class inherits three methods that were declared abstract: getColor(), isAquatic() and livesInFreshWater(). None of these methods were implemented in the classes that BluefinTuna class extended. So, BluefinTuna needs to provide implementations for all these three methods.
public class BluefinTuna extends Fish implements Animal {
public String getColor() {
return “blue”;
}
public boolean isAquatic() {
return true;
}
public boolean livesInFreshWater() {
return false;
}
}
When we take a closer look at our model, we realize that we already know all fish are aquatic. So, it is safe for us to implement this method in the abstract class Fish because this is going to apply all the classes that extend Fish. So, let’s move the isAquatic() method to the Fish class and provide the implementation there.
public abstract class Fish implements Animal {
abstract boolean livesInFreshWater();
public boolean isAquatic() {
return true;
}
}
Now, BluefinTuna class that extends Fish inherits two abstract methods that were not implemented by the classes it extends: getColor() and livesInFreshWater(). Therefore, providing implementations for these two methods is sufficient for BluefinTuna class.
public class BluefinTuna extends Fish implements Animal {
public String getColor() {
return “blue”;
}
public boolean livesInFreshWater() {
return false;
}
}