当前位置: 首页 > 知识库问答 >
问题:

子类型如何“promise”它将调用具有更具体类型的回调?

湛文乐
2023-03-14

这是我最想要的代码,它不会编译:

interface Interface {
  interface ArgumentInterface {
    // Some methods
  }

  void doCallback(Consumer<? super ArgumentInterface> callback);
}

interface SubInterface extends Interface {
  interface ArgumentSubInterface extends ArgumentInterface {
    // Some more methods
  }

  @Override
  void doCallback(Consumer<? super ArgumentSubInterface> callback);
}

这里的想法是,接口将把ArgumentInterface的实例传递给用户提供的消费者,而SubInterface将传递更具体的ArgumentSubInterface的实例。特别是,我希望用户能够传递一个消费者

天真地说,这似乎应该像写的那样工作:任何被Interface版本接受的论点也将被SubInterface版本接受。然而,Java声称该方法不会覆盖。

共有3个答案

长孙嘉容
2023-03-14
interface ArgumentInterface {
  // Some methods
}

interface Interface<IFace extends ArgumentInterface> {

  void doCallback(Consumer<IFace> callback);
}

interface ArgumentSubInterface extends ArgumentInterface {
  // Some more methods
}

interface SubInterface<IFace extends ArgumentSubInterface>
extends Interface<IFace> {

// No need to override anymore, the selection is applied at the 
// SubInterface generics' arguments
//  @Override
//  void doCallback(Consumer<? super ArgumentSubInterface> callback);
}
缑桐
2023-03-14

您说过“任何被< code >接口版本接受的参数也将被< code >子接口的版本接受”。这是正确的,但不是方法重写的工作方式。就好像你写了:

interface Interface {
    void method(String s);
}
interface SubInterface extends Interface {
    void method(Object o);
}

虽然< code>method(Object)能够接受< code>method(String)可以接受的任何内容,但它仍然没有覆盖该方法。在这个简化的示例中,您可以按如下方式解决问题

interface SubInterface extends Interface {
    @Override default void method(String s) {
        method((Object)s);
    }
    void method(Object o);
}

这具有SubInterface实现者必须使用更抽象的类型实现一个方法的预期效果。

但是,当所讨论的参数类型为消费者

interface Interface {
    interface ArgumentInterface {
      // Some methods
    }
    void doCallback(Consumer<? super ArgumentInterface> callback);
}

interface SubInterface extends Interface {
    interface ArgumentSubInterface extends ArgumentInterface {
      // Some more methods
    }
    @Override
    default void doCallback(Consumer<? super ArgumentInterface> callback) {
        doCallbackSub(callback);
    }
    void doCallbackSub(Consumer<? super ArgumentSubInterface> callback);
}

我想这不是你能想象的最好的,但Java泛型是你能得到的最好的…

柳和怡
2023-03-14

它不起作用,因为Java不允许使用逆变参数覆盖。您可以用您要接受的ArgumentInterface的特定类型参数化Interface

interface Interface<T extends ArgumentInterface> {
  interface ArgumentInterface {
    // Some methods
  }

  void doCallback(Consumer<? super T> callback);
}

interface SubInterface extends Interface<ArgumentSubInterface> {
  interface ArgumentSubInterface extends ArgumentInterface {
    // Some more methods
  }

  // This is implicitly inherited
  // @Override
  // void doCallback(Consumer<? super ArgumentSubInterface> callback);
}
 类似资料:
  • 问题内容: 对于一个抽象类,我想定义一个为子类返回“ this”的方法: 我希望能够执行以下操作: 可以说香蕉面包会抛出一个IllegalArgumentException消息“不是蛋糕!”。 问题答案: 编辑 要求子类以某种方式表现是没有问题的,这超出了静态类型可以检查的范围。我们一直在这样做-一页又一页的普通英语指定您如何编写子类。 提出的另一种具有协变返回类型的解决方案必须做同样的事情-用简

  • 当使用使用回调的第三方函数时,我试图返回指定的类型。我有一个接口 在实现接口时,我调用了一个使用回调的AWS Cognito异步函数。 在调用此方法时,如何仍返回身份验证结果的类型(注册在后台)?(我不想将其更改为 void,以便我可以在界面上使用匕首)。 编辑 我在dagger中尝试了许多不同的方法,但都不成功。我试图将下面的界面作为一个字段注入到一个活动中。 组件 然后我得到三个声明的错误,这

  • 我不熟悉泛型。我有一个抽象类(1)和一个抽象方法。我有另一个抽象类(2)和一些抽象方法,我希望在一些DTO(3,4)中共享这些抽象方法。我想要一个(1)的具体扩展来处理任何扩展(2)的东西。 1. 扩展StagingError的两个类:3.

  • 我为协变返回类型的继承创建了一个小示例。基本上有三种不同的类别: 主应用程序: BaseManager: 鸟经理: 当我重写方法以返回时,为什么我需要将类型转换为? 我使用过的重写方法在返回类型上会有所不同吗?作为参考。 编辑: 我有不同的子模型,它们都继承自。所有模型都允许存在一次。我尝试将这些模型添加到列表中,而不是对每个模型使用单例。使用,我想得到实际的模型。也许我得考虑太多了。

  • 问题内容: 我正在玩Go,发现一个我无法解决的问题。假设我有如下代码: 我导入了软件包并开始使用它: 我真的很喜欢我的助手“运行”,但是我想使其更加慷慨:我不希望人们总是向我传递MySQL客户端。可以是具有“ RunQuery”和“ Result”方法的任何东西。所以我尝试使用接口: 可悲的是,这不再编译了。我收到此错误: Go不支持此功能吗,或者我做错了什么? 问题答案: 应该返回接口,否则你总

  • (沙盒) 获取此错误: 类型“number”不可分配给类型“T”“number”可分配给“T”类型的约束,但“T”可以用约束{}的不同子类型实例化。(2322)输入。ts(1,26):预期类型来自此签名的返回类型。 我希望typescript能够自动推断T为数字,然后直接使用它。为什么它在抱怨?写这样的东西的正确方法是什么?谢谢