Concrete Inheritance and Interface Inheritance

0

Most of us already know what is inheritance but its important that we know the different ways of inheritance. In this article, I will show you an example of concrete inheritance and interface inheritance.

Concrete Inheritance

Java doesn’t support multiple class inheritance but it does support multiple interface inheritance. First we should know what is concrete inheritance.
Concrete inheritance is inheritance of method implementations and member variables from a super-class. Java allows concrete inheritance from only a single super-class. For example:

A:

package javarticles.javainheritance;

public class A {
    protected int mVar = 1;
    
    public A() {
        System.out.println("A's constructor");
    }
    
    protected void doSomething() {
        System.out.println("A's doSomtehing(), var value: " + mVar);
    }
}

B:

package javarticles.javainheritance;

public class B extends A {
    
    public B() {
        System.out.println("B's constructor");
    }
    
    protected void doSomething() {
        mVar = 2;
        super.doSomething();
        System.out.println("B's doSomtehing()");
    }
}

Invoke B.doSomething()

JavaInheritanceTests:

package javarticles.javainheritance;

import org.junit.Test;

public class JavaInheritanceTests {
    
    @Test
    public void callB() {
        B b = new B();
        b.doSomething();
    }

}

Output:

>A's constructor
B's constructor
A's doSomtehing(), var value: 2
B's doSomtehing()

C:

package javarticles.javainheritance;

public class C extends B {
    
    public C() {
        System.out.println("C's constructor");
    }
    
    protected void doSomething() {
        mVar = 3;
        super.doSomething();
        System.out.println("C's doSomtehing()");
    }
}

Invoke C.doSomething()

    @Test
    public void callC() {
        C c = new C();
        c.doSomething();
    }

Output:

A's constructor
B's constructor
C's constructor
A's doSomtehing(), var value: 2
B's doSomtehing()
C's doSomtehing()

Since Class C extends B, C, B and A are said to be in the same inheritance hierarchy.

Interface inheritance

Interface inheritance is nothing but the implementation of interfaces. A class may implement any number of interfaces.

For example:

Suppose I have three interfaces each representing one feature.

IFeature1:

package javarticles.javainheritance;

public interface IFeature1 {
    public void doFeature1();
}

IFeature2:

package javarticles.javainheritance;

public interface IFeature2 {
    public void doFeature2();
}

IFeature3:

package javarticles.javainheritance;

public interface IFeature3 {
    public void doFeature3();
}

D:

package javarticles.javainheritance;

public class D implements IFeature1 {
    @Override
    public void doFeature1() {
        System.out.println("do Feature1 in D");        
    }
}

G:

package javarticles.javainheritance;

public class G implements IFeature2 {
    @Override
    public void doFeature2() {
        System.out.println("do Feature2 in G");        
    }
}

Class E implements feature3. Since it extends D it also ends up implementing feature1.

E:

package javarticles.javainheritance;

public class E extends D implements IFeature3 {
    @Override
    public void doFeature3() {
        System.out.println("do Feature3 in E");
    }
}

Class hierarchies are rigid, use object composition instead

If we want class E to inherit feature2, we won’t be able to do it through inheritance as E already extends D and we don’t want to change the inheritance hierarchy.

But we can do it through delegation using object composition. For example, Class E is modified to delegate to G's doFeature2()

E:

package javarticles.javainheritance;

public class E extends D implements IFeature3, IFeature2 {
    private IFeature2 g = new G();
    @Override
    public void doFeature3() {
        System.out.println("do Feature3 in E");
    }

    @Override
    public void doFeature2() {
        g.doFeature2();        
    }
}

Another example of object composition:
Class F below implements all three features and delegates call to E's features.

F:

package javarticles.javainheritance;

public class F implements IFeature1, IFeature2, IFeature3 {
    private E e = new E();

    @Override
    public void doFeature3() {
        e.doFeature3(); 
        System.out.println("do Feature3 in F");
    }

    @Override
    public void doFeature2() {
        e.doFeature2();     
        System.out.println("do Feature2 in F");
    }

    @Override
    public void doFeature1() {
        e.doFeature1();
        System.out.println("do Feature1 in F");
    }
}

This is a perfect example of object composition where functionality is inherited using delegation. This is more flexible than the concrete inheritance as we are not forced to extend a specific class just to inherit a method. Object composition allows the behavior of an object to be altered at run time through delegating part of its behavior to interface and allowing callers to set the implementation of that interface.

Download source code

In this article, we have seen examples of concrete inheritance and object composition.

You can download the source code here: javainheritance.zip
Share.

Leave A Reply