开发者

Generics confusion

Apologies for the generic title, I can't really think of a way to explain this.

I'd like to model a scenario where a system provides facilities to users, which have associated policies applied to requests against those facilities.

public interface Facility {
    public List<Policy> getPolicies();
}
public interface Policy {
    public void apply(Facility facility, Request request);
}
public interface Request {

}

But a request can only be sensible for a particular type of facility, and a policy can really only apply to a type of facility and a type of request specific to that type of facility.

public interface Facility<F extends Facility<F>> {
    public List<Policy<F, ? extends Request<F>>> getPolicies();
}
public interface Policy<F extends Facility<F>, R extends Request<F>> {
    public void apply(F facility, R request);
}
public interface Request<F extends Facility<F>> {

}

But I'd also like to be able to specify policies overall, such that they can apply to any Facility supertype.

public interface Facility<F extends Facility<F>> {
    public List<Policy<? super F, ? 开发者_StackOverflowextends Request<F>>> getPolicies();
}

But in reality you're only ever going to want to query the policies that apply to a particular type of request for the facility.

public interface Facility<F extends Facility<F>> {
    public <R extends Request<F>> List<Policy<? super F, R>> getPolicies();
}

My problem is now I'm so confused with all the generics and I'm not able to even create a policy class that applies to all Facilities, which would be something like this, if it were legal

public class GeneralPolicy implements Policy<T extends Facility<T>, Request<T>>

How do I go about making it possible to associate types of facility, policy and request in such a way that makes sense according to the description above? I'm sure people will ask for clarification, I've battled with this long enough that I'm probably not explaining something, or completely missing an obvious point.


If I read this correctly, what you really want to do is get all the policies that work for R.

public interface Facility<F extends Facility<F>> {
    public <R extends Request<F>> List<Policy<? super F, R>> getPolicies();
}

Unfortunately, thanks to type erasure, you can't. At runtime, the compiler doesn't know what R is.

What you can do, however, is pass the class in:

public interface Facility<F extends Facility<F>> {
    public <R extends Request<F>> List<Policy<? super F, R>> getPolicies(Class<R> requestClass);
}

Then Policy would need to return its request type as well:

public interface Policy<F extends Facility<F>, R extends Request<F>> {
    public void apply(F facility, R request);

    public Class<R> getRequestClass();
}

The implementation of facility can then though the list of available policies, check if the policy's request type matches the actual requested type, and return that subset.

For global policies, the policy could return Request.class. For specific ones, MyRequest.class.

Furthermore, I'd say that Facility (at least the way you have it there) doesn't need to be genericized, and it'll make the code much simpler.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜