如何将类型参数的值绑定到`this`的类型?

时间:2017-02-13 02:11:46

标签: java generics type-parameter

interface A<T extends B</*?*/>> {
    method(T param);
}

interface B<U extends A> {
    // ...
}

在上面的代码片段中,如何表达方法A#method应该只接受参数,这些参数是由调用该方法的类型(或其后代)参数化的对象。

我想得到这样的东西:

interface Vehicle<T extends SteeringDevice</*?*/> {
    default steer(T steeringDevice) {
        // ...
    }
}

interface SteeringDevice<U extends Vehicle> {
    // ...
}

// -----

class Car implements Vehicle<SeeringWheel> {
    // ...
}

class SteeringWheel implements SteeringDevice<Car> {
    // ...
}

// -----

class Bike implements Vehicle<Handlebars> {
    // ...
}

class Handlebars implements SteeringDevice<Bike> {
    // ...
}

...可以安全地拨打new Car().steer(new SteeringWheel())而不是new Car().steer(new Handlebars())

1 个答案:

答案 0 :(得分:2)

我认为这可以满足您的需求:

interface Vehicle<T extends SteeringDevice<? extends Vehicle<T>>> {
    default void steer(T steeringDevice) {}
}

interface SteeringDevice<U extends Vehicle<? extends SteeringDevice<U>>> {
    // ...
}

这会强制两个兼容的实现相互交叉引用。将参数更改为不兼容类型现在将在配对类中触发编译错误。

上述一个潜在问题是它允许SteeringDevice<Car>的多个实现。您可以通过添加自我类型参数使配对更加明确:

interface Vehicle<U extends Vehicle<U, T>, T extends SteeringDevice<T, U>> {
    default void steer(T steeringDevice) {}
}

interface SteeringDevice<T extends SteeringDevice<T, U>, U extends Vehicle<U, T>> {
    // ...
}

class Car implements Vehicle<Car, SteeringWheel> {
    // ...
}

class SteeringWheel implements SteeringDevice<SteeringWheel, Car> {
    // ...
}

仍然可以创建SteeringDevice<SteeringWheel, Car>的另一个实现,因为Java没有真正的自我类型,但至少它会使违规更加明显。它还具有在无效类型参数上打破两个类的优点。