【问题标题】:Kotlin: Override (and specify) generic interface functionsKotlin:覆盖(并指定)通用接口函数
【发布时间】:2020-10-19 13:47:18
【问题描述】:

我想使用由它们的实现类指定的通用接口,总而言之,这一切都很好,比如:

interface Remove <E> { fun remove(entity: E) }

class MyHandler : Remove <MyClass> {
   override fun remove(entity: MyClass) { */do stuff/* }
}

但是,我有一个案例(到目前为止,期待更多),我希望函数本身是通用的。写界面一点问题都没有:

interface FindByID <E> { fun <K : Serializable> findByID(id: K): E }

我需要 K 是可序列化的,因为这是我需要调用的某些函数的要求。

编译器似乎不同意我的实现尝试。当我这样做时:

override fun <String> findByID(id: String): User {
    return someFunction(User::class.java, id) as User
}

我得到两个编译器错误:

  1. 不覆盖任何内容
  2. id 不可序列化

但是,当我从签名中删除 override&lt;String&gt; 时,它工作正常。这意味着String 是可序列化的,我的研究也表明了这一点。

这里似乎有什么问题?

另外,是的,我知道我可以通过多种方式解决这个问题,比如

  • 使接口函数接受Serializable 而不是&lt;K : Serializable&gt;
  • 不指定 K 覆盖,但随时待命 (myHandler.findByID&lt;String&gt;("myID"))
  • “重新路由”调用,在 MyHandler 中实现(而不是覆盖)一个接受字符串的函数,然后在内部调用被覆盖的函数

虽然我愿意接受建议,但我对解决方法不太感兴趣,但更愿意了解并(如果可能)解决实际问题,或者至少知道它无法完成,因此我可以在规划时考虑到这一点

【问题讨论】:

  • 如果我在关注,接口承诺您可以使用 any 类型 K 调用该方法 - 但您的实现正试图将其限制为特定类型,这就是不允许的原因。您是否尝试过将类型参数K 移动到界面上?然后你可以在实现类中修复它。

标签: function kotlin generics interface overriding


【解决方案1】:

当前的问题

使用您当前的&lt;String&gt; 声明,您并没有像您想象的那样专门化类型参数。您实际上在做的是声明一个恰好名为String 的类型参数(与众所周知的String 类型无关,只是不幸的名称冲突)。使用语法着色,您应该看到 String 这里是类型参数的颜色,与 String 类型的颜色不同。将此名称更改为其他任何名称,您就会意识到混乱。

所以如果我们把它重命名为K,问题就很明显了:问题1“覆盖什么”是因为你的泛型类型参数没有与接口中定义的findByID方法相同的: Serializable约束.而问题 2 正是源于此。

解决方案

另外,是的,我知道我可以通过多种方式解决这个问题,比如

  • 没有在覆盖时指定 K,而是在调用时 (myHandler.findByID("myID"))

这一点实际上是问题的本质,而不是解决方法:在你的接口中定义一个泛型函数实际上使它成为该函数是泛型的合同的一部分。 实现必须在这里有一个泛型类型参数。

如何解决它取决于您预期会发生什么。

如果您可以在实现中使用泛型函数,则保留您声明的接口,但接受实现必须处理 K 的所有可能值,这很可能不是您想要的在这里。

如果你想在你的实现中定义一个特定的类型,K应该是接口定义的一部分(不是接口方法),并且方法本身不应该有类型参数,而只是接受现有的@987654330 @来自界面:

interface FindByID<E, K : Serializable> {
  fun findByID(id: K): E
}

【讨论】:

  • 谢谢!我曾考虑过您的最终建议(K 是接口定义的一部分),但将其作为另一个“解决方法”丢弃了,因为我基本上是脑残,不知何故认为我以后可以结合覆盖和重载,即具有相同的功能(findByID(id))重载通过为 K 提供不同的类型。考虑到每个实现都是模棱两可的,我意识到这是愚蠢的 (findbyID(Serializable))
猜你喜欢
  • 2020-10-29
  • 2011-04-11
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
相关资源
最近更新 更多