JavaRush /Java Blog /Random EN /Coffee break #140. Abstract classes and interfaces in Jav...

Coffee break #140. Abstract classes and interfaces in Java

Published in the Random EN group
Source: InfoWorld Today you will learn in which cases a developer should use an abstract class and in which cases an interface. We will also identify the differences between these elements of the Java language and how to use them in programs. Coffee break #140.  Abstract classes and interfaces in Java - 1Abstract classes and interfaces are quite common in Java code and even in the Java Development Kit (JDK) itself. Each of these elements serves a different purpose:
  • An interface is a construct in the Java language that helps implement abstract methods and static constants.
  • Abstract classes are similar to regular classes, except that they can include abstract methods, that is, methods without a body. Abstract classes cannot be created.
Many developers think that interfaces and abstract classes are similar, but in reality this is not entirely true. Let's look at the main differences between them.

What is an interface

At its core, an interface is a contract, so it depends on the implementation to define the purpose for its creation. The interface cannot use mutable instance variables, it can only use final variables.

When to use interfaces

Interfaces are very useful for separating code and implementing polymorphism. We can see this in the JDK with the List interface :
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean add(E e);
    E remove(int index);
    void clear();
}
As you've probably noticed, this code, although brief, is quite descriptive. We can easily see the method signature that will be used to implement the methods in the interface using the concrete class. The List interface contains a contract that can be implemented by the ArrayList , Vector , LinkedList , and other classes. To use polymorphism, we can simply declare the type of our variable using List and then select any of the available instances. Here's another example:
List list = new ArrayList();
System.out.println(list.getClass());

 List list = new LinkedList();
 System.out.println(list.getClass());
The output is:
class java.util.ArrayList class java.util.LinkedList
In this case, the implementation methods for ArrayList , LinkedList , and Vector are different, which is an excellent scenario for using the interface. If you notice that many classes belong to a parent class with the same method actions but different behavior. In such situations, it is recommended to use the interface. Next, let's look at several options for using interfaces.

Interface Method Overriding

As we already know, an interface is a kind of contract that must be implemented by a concrete class. Interface methods are implicitly abstract and require a concrete implementation of the class. Here's an example:
public class OverridingDemo {
  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }
}

interface Challenger {
  void doChallenge();
}

class JavaChallenger implements Challenger {
  @Override
  public void doChallenge() {
    System.out.println("Challenge done!");
  }
}
Conclusion:
Challenge done!
Note that interface methods are implicitly abstract. This means that we don't need to explicitly declare them abstract.

Constant Variables

Another rule to remember is that an interface can only contain constant variables. Here's an example:
public class Challenger {

  int number = 7;
  String name = "Java Challenger";

}
Here both variables are implicit final and static . This means that they are constant, independent of the instance, and cannot be changed. Now we will try to change the variables in the Challenger interface , let's say like this:
Challenger.number = 8;
Challenger.name = "Another Challenger";
This will cause a compilation error:
Cannot assign a value to final variable 'number' Cannot assign a value to final variable 'name'

Default Methods

When default methods were introduced in Java 8, some developers thought they would be the same as abstract classes. However, this is not true because interfaces cannot have state. A default method may have an implementation, but abstract methods do not. Default methods are the result of innovations with lambda expressions and streams, but we must use them carefully. The method in the JDK that uses the default method is forEach() , which is part of the Iterable interface . Instead of copying the code into each Iterable implementation , we can simply reuse the forEach method :
default void forEach(Consumer<? super T> action) {
  // Code implementation here...
Any Iterable implementation can use the forEach() method without requiring a new method implementation. We can then reuse the code with the default method. Let's create our own default method:
public class DefaultMethodExample {

  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }

}

class JavaChallenger implements Challenger { }

interface Challenger {

  default void doChallenge() {
    System.out.println("Challenger doing a challenge!");
  }
}
Result:
Challenger doing a challenge!
With regard to default methods, it is important to note that each such method needs to be implemented. The default method cannot be static. Now let's move on to abstract classes.

The essence of an abstract class

Abstract classes can have state with instance variables. This means that the instance variable can be used and modified. Here's an example:
public abstract class AbstractClassMutation {

  private String name = "challenger";

  public static void main(String[] args) {
    AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
    abstractClassMutation.name = "mutated challenger";
    System.out.println(abstractClassMutation.name);
  }

}

class AbstractClassImpl extends AbstractClassMutation { }
Conclusion:
mutated challenger

Abstract methods in abstract classes

Like interfaces, abstract classes can have abstract methods. An abstract method is a method without a body. Unlike interfaces, abstract methods in abstract classes must be explicitly declared abstract. Here is an example:
public abstract class AbstractMethods {

  abstract void doSomething();

}
And here is an attempt to declare a method without an implementation and without the abstract keyword :
public abstract class AbstractMethods {
   void doSomethingElse();
}
Unfortunately, it results in a compilation error:
Missing method body, or declare abstract

When to use abstract classes

An abstract class is recommended when you need to implement mutable state. For example, the Java Collections Framework includes an AbstractList class that uses the state of variables. In cases where you don't need to maintain class state, it's usually better to use an interface.

Differences between abstract classes and interfaces

From an object-oriented programming perspective, the main difference between an interface and an abstract class is that an interface cannot have state, whereas an abstract class can have state with instance variables. Another key difference is that classes can implement more than one interface, but they can only extend one abstract class. This solution is based on the fact that multiple inheritance (extending more than one class) can lead to code deadlock. The developers of the Java language decided to avoid this. Another difference is that interfaces can be implemented by classes or extended by interfaces, but classes can only be extended. It is important to note that lambda expressions can only be used with a functional interface (meaning an interface with only one method), while abstract classes with only one abstract method cannot use lambda expressions. Here are some more differences between abstract classes and interfaces. Interface:
  • Can only have final static variables. An interface can never change its own state.
  • A class can implement multiple interfaces.
  • Can be implemented using the implements keyword. An interface can extend another interface.
  • Methods can only use static final fields, parameters, or local variables.
  • Only functional interfaces can use the lambda function in Java.
  • Cannot have a constructor.
  • May have abstract methods.
  • Can have default and static methods (introduced in Java 8).
  • Can have private methods with implementation (introduced in Java 9).
Abstract classes:
  • Can have any instance or static variables, mutable or immutable.
  • A class can only extend one abstract class.
  • May have an instance of mutable fields, parameters, or local variables.
  • Abstract classes with only one abstract method cannot use lambda expressions.
  • May have a constructor.
  • Can have any methods.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION