【问题标题】:Type bounds: Propagate parameter with multiple bounds类型边界:传播具有多个边界的参数
【发布时间】:2015-09-23 14:34:53
【问题描述】:

考虑以下(不可更改的)API:

interface Bar {}
class Foo {
    public static <T extends Foo & Bar> void doFoo(T param) {
         System.out.println("I shall be your ruler");
    }
}

现在我已经编写了一个接受通用Foo 的类,但如果该参数也是Bar,我想在某些方法中另外执行doFoo

class Holder {
    public Holder(Foo foo) {
        this.foo = foo;
    }
    public void takeOverTheWorld() {
        if(this.foo instanceof Bar) {
            // Here I want to execute doFoo(), but I can't hand it over
            // because the bounds don't match
            // doFoo(this.foo);
        )
        // Enstablish my reign
    }
}

Holder 的用法示例:

class Yes extends Foo implements Bar {
}
// ------
Holder h = new Holder(new Yes());
h.takeOverTheWorld(); // Should print "I shall be your ruler"

正如代码 cmets 中所述,我在 Holder 类中调用 doFoo() 时遇到问题,因为当时不知道扩展 Foo 实现 Bar 的确切类型,所以我不能简单地将它转换为这种类型。有没有办法在不改变HolderFooBar的接口的情况下解决这个问题?

【问题讨论】:

    标签: java generics type-bounds


    【解决方案1】:

    您可以在私有辅助方法中调用doFoo,该方法为强制转换引入正确的类型:

    public void takeOverTheWorld() {
        if(this.foo instanceof Bar)
            doBarFoo();
    }
    
    private <T extends Foo & Bar> void doBarFoo() {
        Foo.doFoo((T)this.foo);
    }
    

    如果您不介意该类型是公共接口的一部分,您甚至可以在 takeOverTheWorld 中执行此操作:

    public <T extends Foo & Bar> void takeOverTheWorld() {
        if(this.foo instanceof Bar)
            Foo.doFoo((T)this.foo);
    }
    

    【讨论】:

    • 我会记住这一点:如果你不能正常做,总是通过私有方法“推断”类型,哈哈
    【解决方案2】:

    创建 Holder 的通用子类:

    class SubHolder<T extends Foo & Bar> extends Holder {
      private T fooT;
    
      SubHolder(T foo) {
        super(foo);
        this.fooT = fooT;
      }
    
      @Override void takeOverTheWorld() {
        Foo.doFoo(fooT);
      }
    }
    

    【讨论】:

    • 这将改变 Holder 的接口,因为该类现在将是通用的,仅用于执行除该类之外没有人必须知道的事情。就封装而言,这不是一个很好的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2021-06-21
    相关资源
    最近更新 更多