Java抽象类获取扩展类的类型

时间:2018-10-12 05:28:10

标签: java

我没有这个短语,所以我去举一个例子

class AbstractUser<A extends AbstractAccount<? extends AbstractType>> {
    // I want a method that has access to Type
    // And returns the specific Type that extends AbstractType
    protected <T extends AbstractType> T doSomething(T type) {
        // do stuff
        // and return the type specific type T
    }
}

class AbstractAccount<T extends AbstractType> {

}

class AbstractType {

}


class Type extends AbstractType {

}

class Account extends AbstractAccount<Type> {

}

class AccountAdmin extends AbstractAccount<Type> {

}

class User extends AbstractUser<Account> {

}

我想要的是在User类中我可以做getType(),它返回特定类型的AbstractAccount,在这种情况下为Account

如何在不指定其他模板的情况下执行此操作?换句话说,我希望该方法中?? extends AbstractType的任何类型

所以我愿意

final Account account = ...
final AccountAdmin admin = ...
final User user = ...
user.doSomething(account); // should work
user.doSomething(AccountAdmin); // should fail

3 个答案:

答案 0 :(得分:4)

您显然无法在AbstractUser中创建这样的方法:

public Class<A> getType() { return A.class; }

这是因为类型擦除。运行时不知道A是什么。

一种解决方法是使此方法抽象化:

public abstract Class<A> getType();

现在,您可以在子类中实现此方法:

class User extends AbstractUser<Account> {
    public Class<Account> getType() { return Account.class; }
}

编辑:

现在,我意识到您想要扩展AbstractType的类型,解决方法仍然可以使用。您只需要在getType中创建另一个AbstractAccount,并使Account实现该方法。

答案 1 :(得分:1)

为此,您实际上无法绕开AbstractUser中的另一个类型参数:

class AbstractUser<T extends AbstractType, A extends AbstractAccount<T>> {
    protected abstract T getType();
}

您需要一种方法来引用A的type参数的类型,这可以达到目的。

答案 2 :(得分:0)

从Java 8开始,您可以定义一个构造函数,该构造函数使用Supplier返回适当类型的实例。

您说:
我想要的是在User类中可以执行getType()并返回特定类型的AbstractAccount,在这种情况下为Account。

您要:doSomething(T type)
因此,我假设您不希望使用Class<T>的实例,而需要T的实例。根据您的示例,此T应该为Account

据此:

class AbstractUser<T extends AbstractType, A extends AbstractAccount<T>> {

    private Supplier<T> accountSupplier;

    public AbstractUser(Supplier<T> accountSupplier) {
        this.accountSupplier = accountSupplier;
    }

    protected T getType() {
        return accountSupplier.get();
    }
}

然后类User如下所示:

class User extends AbstractUser<Type, Account> {

    public User() {
        super(Account::new);
    }
}

请注意,类AbstractUser仍未声明为abstract。如果拥有此类的唯一原因是通过子类提供不同类型的AbstractAccount,那么现在我们可以在没有子类的情况下做到这一点。

User user = new User();可以重写为AbstractUser user = new AbstractUser(Type::new); (在这种情况下,AbstractUser不是最好的名字)