2

I understand that Java does not have multiple inheritance.

I'm reading Effective Java 3rd Edition Item 20 (page 102), here is a portion from the page:

The beauty of skeletal implementation classes is that they provide all of the implementation assistance of abstract classes without imposing the severe constraints that abstract classes impose when they serve as type definitions. For most implementors of an interface with a skeletal implementation class, extending this class is the obvious choice, but it is strictly optional. If a class cannot be made to extend the skeletal implementation, the class can always implement the interface directly. The class still benefits from any default methods present on the interface itself. Furthermore, the skeletal implementation can still aid the implementor’s task. The class implementing the interface can forward invocations of interface methods to a contained instance of a private inner class that extends the skeletal implementation. This technique, known as simulated multiple inheritance, is closely related to the wrapper class idiom discussed in Item 18. It provides many of the benefits of multiple inheritance, while avoiding the pitfalls.

Since English is not my native language, the bold part of the quote got me confused. And I got no result when search for the answer.

What is this private inner class? Is this like a normal inner class?

In practice, does this technique get use very often?

Any code example would be extremely useful for me to visualize!

Thank you!

5
  • Take a look here. It may not answer your question, but is useful I guess. Commented Mar 19, 2022 at 19:19
  • @Zakk Thank you. But I already read it before I ask the question. Unfortunately, without an example, I still cannot visualize it correctly. Commented Mar 19, 2022 at 19:23
  • "Is this like a normal inner class?" Yes, it is. I don't know if this answers your question. Commented Mar 19, 2022 at 19:45
  • @Zakk Thank you. I think I found the answer from this useful article. It has a nice example but never mentions simulated multiple inheritance but I guess that's acceptable. Commented Mar 19, 2022 at 19:57
  • So, please answer your own question and mark it as the accepted one. This way, others can benefit from it. Commented Mar 19, 2022 at 20:00

2 Answers 2

1

What is this private inner class?

An example:

class OuterClass {
    private class InnerClass {
        {
            
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I understand the private inner class now but my main question is about simulated multiple inheritance. Any concrete code example? Thanks!
0

Suppose we have an interface called Shape that represents geometric shapes with methods for calculating area and perimeter.

We will create a skeletal implementation class AbstractShape that provides default implementations for these methods, and then we will have a class Circle that directly implements the Shape interface but also reuses code from AbstractShape by forwarding method calls to an inner class.

// Interface representing a geometric shape
interface Shape {
    double getArea();
    double getPerimeter();
}

// Skeletal implementation class providing default implementations
abstract class AbstractShape implements Shape {
    // Common method implementations for all shapes
    @Override
    public double getArea() {
        return 0.0;
    }

    @Override
    public double getPerimeter() {
        return 0.0;
    }
}

// Class representing a Circle, which directly implements Shape
class Circle implements Shape {
    private final double radius;

    // Constructor for Circle
    public Circle(double radius) {
        this.radius = radius;
    }

    // Inner class that extends the skeletal implementation
    private class CircleImpl extends AbstractShape {
        @Override
        public double getArea() {
            return Math.PI * radius * radius;
        }

        @Override
        public double getPerimeter() {
            return 2 * Math.PI * radius;
        }
    }

    // Forward method calls to the inner CircleImpl instance
    private final CircleImpl circleImpl = new CircleImpl();

    @Override
    public double getArea() {
        return circleImpl.getArea();
    }

    @Override
    public double getPerimeter() {
        return circleImpl.getPerimeter();
    }
}

public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(5.0);
        System.out.println("Circle Area: " + circle.getArea());
        System.out.println("Circle Perimeter: " + circle.getPerimeter());
    }
}

In this example, AbstractShape serves as a skeletal implementation of the Shape interface, providing default implementations for getArea() and getPerimeter(). The Circle class directly implements the Shape interface, but it also has an inner class CircleImpl, which extends AbstractShape and provides specific implementations for getArea() and getPerimeter() tailored to circles.

By forwarding the method calls to the inner CircleImpl instance, the Circle class is effectively reusing the code from AbstractShape without having to extend it directly.

This allows the Circle class to benefit from the implementation assistance provided by the skeletal implementation, while still being free to implement other interfaces or extend different classes as needed.

This is what is referred to as simulated multiple inheritance in Java and as you can see it's way more flexible than using only polymorphism and inheritance.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.