3

I just want to know that can i have 2 classes A and B. I don't want to allow class B to extends class A. What technique should i apply in class A so class B cannot inherit class A. Don't want to make class A final. Any other solution instead of making class A final?

Muhammad Zahab
  • 1,049
  • 10
  • 21

7 Answers7

3

In fact, the practice that I try to follow, and that Josh Bloch recommends, in his Effective Java book, is exactly the inverse rule of the one you've been told: Unless you have thought about inheritance, designed your class to be inherited, and documented how your class must be inherited, you should always disable inheritance.

I would recommend reading this chapter of Effective Java (you won't regret buying it), and showing it to the person who told you about this rule.

The most obvious reason to disallow inheritance is immutability. An immutable object is simple to use (only one state), can be cached, shared between many objects, and is inherently thread-safe. If the class is inheritable, anyone can extend the class and make it mutable by adding mutable attributes. https://stackoverflow.com/a/10464466/5010396

chdanish
  • 43
  • 5
1

This is not possible in "nice ways". The java language allows you to either have the final keyword on your class definition, or to not have it.

As pointed out by others: you can make all constructors private, then subclassing becomes practically impossible, as the subclass constructors have no super class constructor to call.

In case you need to instantiate A, you could still have a factory method, like:

public class A {
  private A() { ... }
  private A(String foo) { ... }

  public static A newInstance(String foo) { return new A(foo); }

for example.

But keep in mind: code is written for your human readers. If your intent is to have a final class, then the correct answer is to use that keyword final.

Plus: making your class final allows the JIT to do a few more things, as it doesn't have to worry about polymorphism at any point (so it can directly inline method code, without any additional checks). So using final can result in slightly improved performance. On the other hand, it limits your ability to unit test things (for example: standard Mockito can't mock final classes).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    So basically the technique provided here isn't an alternative? https://www.developer.com/java/other/article.php/3109251/Stopping-Your-Class-from-Being-Inherited-in-Java-the-Official-Way-and-the-Unofficial-Way.htm – dbl Sep 11 '18 at 07:57
  • 1
    @dbl Uups. I forgot about that, and I was updating the answer after you commented. Hope it makes more sense now ;-) – GhostCat Sep 11 '18 at 08:01
1

You can mark the constructor of A class as private. :)

PS: If you also want to avoid reflection attacks then throw some Error from constructor and also mark it private.

G.G.
  • 592
  • 5
  • 16
0

I don't understand the specific use case of your requirement but this could work.

If you are open to make changes in B

In B's every constructor check for is it is an instance of A then throw an error.

if(A.class.isAssignableFrom(B.class)) {
        System.out.println(true);
        throw new IllegalStateException();
    }
    else
        System.out.println(false);
Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
  • 3
    That doesn't work. The whole point is to do something in A to prevent B from extending it. So *how* does it help to put code in B here?! – GhostCat Sep 11 '18 at 07:56
  • 1
    Not it **doesn't**. If you know that B shouldnt extend A, then your B does not extend A. Putting code in your own class to prevent it from extending another class is bogus. This gets nothing done. – GhostCat Sep 11 '18 at 08:16
  • Simply remove the `extends A` from class B – Gyro Gearless Sep 11 '18 at 08:17
  • It could work the other way round: in class `A` constructors, check if the actual type is some descendant `B`. – Gyro Gearless Sep 11 '18 at 08:19
  • As per OP *I don't want to allow class B to extends class A.* which means in runtime and B shouldn't be able to extend A; not A should stop B from extending itself. If it was not runtime then obviously dont extend A and no question arises at all. – Rohit5k2 Sep 11 '18 at 08:21
0

You have an option to restrict in constructor like this.

if (this.getClass() != MyClass.class) {
    throw new RuntimeException("Subclasses not allowed");
}

For further details check the post.

https://stackoverflow.com/a/451229/6742601

Fazal Hussain
  • 1,129
  • 12
  • 28
0

You can do one of the following to avoid inheritance without using final keyword:

  • Use private constructor(s).
  • Mark every method final so children can't override them.
  • Throw Runtime exception in the constructor if want to limit inheritance for some unwanted children (although v.rude) e.g
    if (this.getClass() != FavoriteChild.class) throw new RuntimeException("Not Allowed")
Qasim
  • 5,181
  • 4
  • 30
  • 51
0
  1. Declare all constructors of the class as private
  2. Make the class package protected(default access modifier/no access modifier) still this will allow to inherit in same package but not in different package