简体   繁体   中英

Generic within method declaration

Let's say I have an abstract class called which has this abstract method

removeItem(GeneralItem item, String reason);

but then in a subclass I have

removeItem(SpecificItemThatExtendsGeneralItem item, String reason){ //code }

How do I make it so the second removeItem counts as an implementation of the first? eg

removeItem(<? extends GeneralItem> item, String reason);

A method having signature ...

removeItem(SpecificItemThatExtendsGeneralItem item, String reason)

... does not implement ...

removeItem(GeneralItem item, String reason)

... because the latter can accept any GeneralItem , including those that are not SpecificItemThatExtendsGeneralItem .

If you can alter the abstract class, however, then you can make it possible:

abstract class MyAbstractClass <T extends GeneralItem> {
    abstract public void removeItem(T item, String reason);
}

class MySubclass extends MyAbstractClass<SpecificItemThatExtendsGeneralItem> {
    @Override
    public void removeItem(SpecificItemThatExtendsGeneralItem item,
            String reason) {
        // ...
    }
}

In that case, however, note that type MySubclass is then still incompatible with MyAbstractClass<GeneralItem> :

MyAbstractClass<GeneralItem> = new MySubclass();  // ERROR

though it is compatible with MyAbstractClass<?> and MyAbstractClass<SpecificItemThatExtendsGeneralItem> :

MyAbstractClass<?> c = new MySubclass();  // ok
MyAbstractClass<SpecificItemThatExtendsGeneralItem> = new MySubclass(); // ok

If you can change base class, you can generalize the first parameter:

class BaseClass<T extends GeneralItem> {
    void removeItem(T item, String reason) {
    }
}

class SubClass extends BaseClass<SpecificItemThatExtendsGeneralItem> {
    @Override
    void removeItem(SpecificItemThatExtendsGeneralItem item, String reason) {
    }
}

Subclasses cannot change the type they accept in methods. But you can definitely check if the type is what you expect:

removeItem(GeneralItem item, String reason)
{
    if (!(item instanceof SpecificItemThatExtendsGeneralItem))
        throw InvalidArgumentException("Only SpecificItemThatExtendsGeneralItem accepted");
}

However, this would not be checked during compilation time, simply because when someone would call

abstractClassInstance.removeItem(OtherSpecificItemThatExtendsGeneralItem)

the compiler has no way of knowing that this should fail, it does not know which implementation abstractClassInstance is actually of.

It's not possible.

The method:

removeItem(SpecificItemThatExtendsGeneralItem item, String reason){ //code }

does not cover all valid ways of calling the method that you're hoping it overrides. Therefore having a class that (just) implements this method does not fulfil the contract of the parent class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM