JAVA Tutorials

Interfaces and Abstract classes

Abstract classes

In Java language, an abstract class is a class that cannot be instantiated and may or may not contain abstract methods. Both abstract classes and methods are marked with the abstract keyword. Here is an example:

public abstract class Animal {

    // declare fields

    public String color;

    //declare non-abstract methods

    public String getColor() {

        return color;

    }

    public abstract void walk();

}

 

As you can see, an abstract method is a method definition without braces and followed by a semicolon. It does not have an implementation. This code doesn’t compile:

public abstract class Chicken {

     public abstract void peck() {}; // DOES NOT COMPILE

}

 

If you want to have default implementation of a method in your abstract class, you have to use non-abstract methods.
Nonabstract classes cannot contain abstract methods. This code does not compile:

public class Chicken {

     public abstract void peck(); // DOES NOT COMPILE

}

Abstract classes cannot be instantiated, but we can create a subclass of them. Subclasses usually provide an implementation for the abstract methods of the superclass. If they don’t provide implementation, then they have to be declared also as abstract:

public abstract class Mammal extends Animal {

    public abstract void walk();

}

public class Cat extends Mammal {

    public void walk() {

        System.out.println(“The cat uses 4 four limbs for a walk”);

    };

}

In abstract classes, you can declare fields with or without static and final modifiers. And concrete methods can be not just public, but also default, protected or private.

Abstract classes cannot have modifier final. The reason is obvious. Abstract classes are created to be extended by subclasses. The modifier final prohibit class to have subclasses. The following code doesn’t compile:

public final abstract class Tortoise { // DOES NOT COMPILE

}

For the same reason, abstract methods cannot be marked as final. For the same reason, abstract methods cannot be marked as final. Let’s assume that you use modifier final for method. Not it cannot be overridden in subclasses. Therefore, subclasses cannot be concrete. They will be abstract and cannot be instantiated. This code does not compile:

public abstract class Cat {

    public abstract final void meow(); // DOES NOT COMPILE

}

 

Also, abstract methods cannot be private. Think a bit and you will understand the reason. Abstract private methods cannot be accessed from another class. Consequently, subclasses of your abstract class that has a private method cannot see it and override it cannot override it. So, this rule makes sense. An example:

public abstract class Animal {

    private abstract void run(); // DOES NOT COMPILE

}

public class Panther extends Animal {

     private void run() {

         System.out.println(“Animal is running”);

     }

}

The method run() from the class Animal is not visible for the class Panther. This means, that the method would be not be overridden by the method run() of the class Panther. The method run() form Animal is unreachable from all classes, except its own class. 

Let’s try to change the methods modifiers to protected:

public abstract class Animal {

    protected abstract void run(); 

}

public class Panther extends Animal {

     protected void run() {

         System.out.println(“Animal is running”);

     }

}

Now, this code will work.

It is important to remember that non-abstract subclasses have to implement all the abstract methods of the abstract superclass. You can extend an abstract class with another abstract class:

public abstract class Animal {

     public abstract String getName();

}

public class Monkey extends Animal { // DOES NOT COMPILE

}

public abstract class Dog extends Animal {

}

Interfaces

An interface is one of the ways to achieve abstraction in Java language. It can have fields method declarations and methods, but cannot be instantiated. Here is an example of interface:

interface Animal {    

     void run(); 

}

Usually, it does not make sense to have variables in interfaces. More practically is to include constants.  All fields in an interface are public, even without the use of the access modifier:

interface Animal {    

    public static final String name = “Wiki”;

    public String color = “white”;

}

Interfaces contain declarations of methods. After JDK 8, there is a possibility to include methods with implementation, they have to be static or default. After JDK 9,  methods in interfaces can be also private. For example:

interface Animal {    

     default void run() {

        jump();

        System.out.println(“Animal is running!”);

    }

    private void jump() {

        System.out.println(“Animal is jump!”);

    }        

}

As you can see, there is just one reason to create private methods, they can be used in other methods of their interface.

 

Implementing interfaces

For interface implementation, the keyword implements are used. Let’s look at the example:

public interface Animal {    

     public void run();

}

public class Monkey implements Animal {

    @Override

    public void run() {

        System.out.println(“Animal is running!”);

    }    

}

The class has to implement all defined methods of the interface.  If it does not implement all methods, you have to declare it as abstract. This code snippet will compile because class Monkey is abstract:

public interface Animal {    

     public void run();

     public String getName();

}

abstract class Monkey implements Animal {

    @Override

    public void run() {

        System.out.println(“Animal is running!”);

    }    

}

 

Any class can implement any number of interfaces. In this case, the names of all interfaces must be comma-separated. If your class is concrete it has to provide all methods from all interfaces that it implements. Here is an example:

public interface Animal {    

    public void run();

}

public interface Mammal {    

}

public interface BananaLover {

    public void eatBanana();    

}

public class Monkey implements Animal, Mammal, BananaLover {    

    @Override

    public void run() {

        System.out.println(“Animal is running!”);

    }

    @Override

    public void eatBanana() {

        System.out.println(“Animal is eating banana!”);

    }

}

 

Interfaces cannot be marked as final, because it cannot be instantiated directly. The keyword final prohibits inheritance.

One interface can extend another interface or interfaces. In this case, the interface inherits all of the abstract methods as its own abstract methods. A concrete class that implements an interface has to implement all inherited by the interface declarations of methods:

interface Animal {    

    public void run();

}

interface Mammal extends Animal{    

}

interface BananaLover extends Mammal{

    public void eatBanana();    

}

class Monkey implements BananaLover {    

    @Override

    public void run() {

        System.out.println(“Animal is running!”);

    }

    @Override

    public void eatBanana() {

        System.out.println(“Animal is eating banana!”);

    }

}

One interface can extend multiple interfaces:

interface Monkey extends Animal, Mammal, BananaLover{     

}

All interface variables are public, static and final. Therefore, they have to be initialized. If you try to define variable as private or protected the compiler error will be generated. You can skip public static, final modifiers for variables in interface.

public interface Animal {    

    String NAME = “Wiki”;

}

This is equal to this code snippet:

public interface Animal {    

    public static final String NAME = “Wiki”;

}

Default interface methods.

Starting from JDK 8, there is a possibility to provide a default implementation to methods in interfaces. This type of methods is called a default:

public interface Animal {    

    public default void run() {

        System.out.println(“Animal is running!”);

    }

}

 

Classes that implement this interface can override this default to implementation or can provide their own.

We can have a situation with two interfaces that have default methods with the same signature. Let’s assume that some class implements both interfaces. This code does not compile:

interface Animal {    

    public default void run() {

        System.out.println(“Animal is running!”);

    }

}

interface Mammal {    

    public default void run() {

        System.out.println(“Animal is running!”);

    }

}

class Monkey implements Animal, Mammal {    //DOES NOT COMPILE

}

In this case, the compiler will ask to override the method run() in class that implements Animal and Mammal interfaces. This code will compile:

class Monkey implements Animal, Mammal {    

    @Override

    public void run() {

        System.out.println(“Animal is running!”);

    }

}

 

Static interface methods

Since JDK 8, there is a possibility to create static methods in interfaces. It works the same as static methods in classes. Static interface methods cannot be inherited. Thi code does not compile:

interface Jump {

    static int getHeight() {

        return 1;

    }

}

class Kangaroo implements Jump {

    public void jump() {

        System.out.println(“Jumping height “ + getHeight()); // DOES NOT COMPILE

    }

}

To fix this code you need to use the interface name when you use static method:

public void jump() {

        System.out.println(“Jumping height “ + Jump.getHeight());

}

 

Now, the code will work.

Nested interfaces

In Java language is possible to create an interface inside another interface. The syntax of the interface and its implementation will look like this:

interface OuterInterface {

    interface InnerInterface {        

    }

}

class ImplementingClass implements OuterInterface.InnerInterface {

} 

We can also create declare an interface inside a class:

class OuterClass {

    interface InnerInterface {        

    }

}

class ImplementingClass implements OuterClass.InnerInterface {    

}

 

Functional interfaces

Functional interfaces are any interfaces that contain just one abstract method. Its implementation can be a lambda expression. Default and static methods do not count as abstract. You must use the annotation FunctionalInterface for such kind of interfaces:

@FunctionalInterface

interface MyFunctionalInterface {    

    void testMethod();

}

class ImplementingClass {    

    void main(String arg[]) {

        MyFunctionalInterface functionalInterface = () -> {

            System.out.println(“Lambda in action”);

        };

    }

}

Facebook Comments
Tags

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back to top button
Close
Close