Dunaril
Dunaril

Reputation: 2795

How to force an implementing class to inherit from one or another subclass?

I have an abstract class MotherClass and two abstract classes ChildClass1 and ChildClass2 that extend MotherClass.

I wish to make sure that any class extending MotherClass will in fact extend ChildClass1 or ChildClass2. I feel that something is wrong in my tree-based class design. Do you see how to make it properly?

Upvotes: 2

Views: 1585

Answers (3)

Thomas
Thomas

Reputation: 88757

If MotherClass has package visibility and ChildClass1 and ChildClass2 are public and in the same package, you could subclass those two but not MotherClass.

Edit:

Another possibility:

interface Marker {} //note that this is package private

public abstract class Mother<T extends Marker > {}

public class ChildA extends Mother<ChildA> implements Marker {}

public class ChildB extends Mother<ChildB> implements Marker {}

Method:

doSomething(Mother<?> mother() {}

You now couldn't do

class GrandChild extends Mother<GrandChild> {}

This would compile but give you a warning at least:

class GrandChild extends Mother {} //warning like "Mother is a raw type"

Ways without warning:

class GrandChild extends ChildA {} 
class GrandChild extends ChildB {} 

Upvotes: 4

Joachim Sauer
Joachim Sauer

Reputation: 308269

Put this in the constructor of MotherClass:

protected MotherClass() {
  if (!(this instanceof ChildClass1 || this instanceof ChildClass2)) {
    throw new IllegalStateException("Oh noes!");
  }
}

This (admittedly ugly) solution was inspired by SWT which has code like this in it's Widget class:

protected void checkSubclass () {
    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

checkSubclass is called in the only constructor of Widget.

This is done to avoid subclassing SWT widget classes (because that's unsupported and should not be done). Note that checkSubsclass() is not final. So if you really wanted to extend Button (and were prepared to live with the consequences) you could overwrite checkSubclass() as a no-op method.

Upvotes: 2

Vladimir Ivanov
Vladimir Ivanov

Reputation: 43108

Extract common functionality from ChildClass1 and ChildClass2 and move it to MotherClass or some other abstract class derived from MotherClass.

Upvotes: 1

Related Questions