Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force subclasses to use type parameter

Tags:

java

generics

When I create a class with a type parameter:

public abstract class AbstractBox<T> {
    abstract T getContent();
}

then I can still create a subclass without a type parameter:

class SomeBox extends AbstractBox {             // DISALLOW THIS
    @Override
    Something getContent() {
        return null;
    }
}

Can I somehow force subclasses to provide a type parameter (even if it's just Object)? For instance, I want to disallow the above but allow:

class SomeBox extends AbstractBox<Something> {  // ALLOW THIS
    @Override
    Something getContent() {
        return null;
    }
}

EDIT: This is not a duplicate of Can overridden methods differ in return type?. That question asks if overriding methods can return subtypes of the type parameter.

My question asks if I can enforce that any subclass of an abstract with a type parameter must provide a type parameter.

like image 928
fweigl Avatar asked Apr 06 '18 07:04

fweigl


People also ask

How do you enforce a default constructor in Java?

You can't force a particular signature of constructor in your subclass - but you can force it to go through a constructor in your abstract class taking two integers. Subclasses could call that constructor from a parameterless constructor, passing in constants, for example. That's the closest you can come though.

Why do we need bounded type parameters?

There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

Is it possible to declared a multiple bounded type parameter?

Multiple BoundsBounded type parameters can be used with methods as well as classes and interfaces. Java Generics supports multiple bounds also, i.e., In this case, A can be an interface or class. If A is class, then B and C should be interfaces. We can't have more than one class in multiple bounds.

How do I restrict a generic type in Java?

Java For Testers Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.


1 Answers

If you want to check if AbstractBox is provided with a type parameter when extended you can do this:

abstract class AbstractBox<T> {
    protected AbstractBox() {
        // First, find the direct subclass of AbstractBox
        Class<?> cls = getClass();
        while(cls.getSuperclass() != AbstractBox.class)
            cls = cls.getSuperclass();

        // Then, check if it's superclass is parametrized
        if (!(cls.getGenericSuperclass() instanceof ParameterizedType)) {
            throw new RuntimeException("Must parametrize the extension of AbstractBox.");
        }
    }

    abstract T getContent();
}

Getting the direct subclass first is needed so that it doesn't break in the case where a direct subclass extends AbstractBox with a parameter, and is then subclassed again.

Note that this will also accept the case of SomBox extends AbstractBox<String>.

like image 163
Jorn Vernee Avatar answered Sep 28 '22 09:09

Jorn Vernee