Java抽象泛型方法,通配符用具体类型实现



是否可以在java中定义带有通配符的抽象方法,但在实现中使用具体类型

例如:

在抽象类中定义抽象方法,如下所示

public abstract class AbstractAuthorizer {
abstract protected <T extends User> void authorize( T user );
}

实现这样的抽象方法,其中 CorporateUser 扩展了 User:

public class CorporateAuthorizer extends AbstractAuthorizer {
@Override
protected <CorporateUser> void authorize(CorporateUser user){
}
}

不,你不能直接做你要求的事情。但是,您可以获得相同的效果。

当你做一些泛型的东西时,你是在向用户做出承诺:这将适用于任何满足泛型边界的类型。因此,通过在子类中选择特定类型,您就违反了该规则。但是,如果正确定义超类,则可以在满足类型检查器的同时获得所需的行为。不要使函数泛型,而是使类泛型,然后当你对它进行子类化时,你可以选择它所处理的类型。

public abstract class AbstractAuthorizer<T extends User> {
abstract protected void authorize( T user );
}
public class CorporateAuthorizer extends AbstractAuthorizer<CorporateUser> {
@Override
protected void authorize(CorporateUser user) {}
}

抽象类声明了一个将授权任何<T extends User>的方法。 扩展不符合此合同。

一些选项:

  1. 泛化抽象类。

    abstract class AbstractAuthorizer<T extends User> {
    protected abstract void authorize(T user);
    }
    class CorporateAuthorizer extends AbstractAuthorizer<CorporateUser> {
    protected void authorize(final CorporateUser user) {
    // Do authorization.
    }
    }
    
  2. 让扩展执行必要的检查。 类似于(AbstractAuthorizer定义为您拥有的东西(:

    class CorporateAuthorizer extends AbstractAuthorizer {
    protected <T extends User> void authorize(final T user) {
    if (!(user instanceof CorporateUser)) {
    throw new UnsupportedOperationException("CorporateAuthorizer can only authorize 'CorporateUser' users");
    }
    // Do authorization.
    }
    }
    

如果您要使用后者,我强烈建议您使用额外的abstract boolean supports(User user);,该执行上述instanceof检查,以便它可以用作:

boolean checkAuth(final User user) {
boolean authorized = false;
for (final AbstractAuthorizer authorizer : authorizers) {
if (authorizer.supports(user)) {
authorizer.authorize(user);
authorised = true;
// break; if only a single authorizer's check is required.
}
}
return authorised;
}

我还要指出,后者中带有<T extends User>的方法与简单地使用User没有任何好处,除非您要在授权的情况下returnUser。 即,

abstract class AbstractAuthorizer {
abstract boolean supports(User user);
abstract <T extends User> T authorize(T user);
}

最新更新