【问题标题】:Invoking a method with a generic type in Kotlin with multiple parameter type constraints在具有多个参数类型约束的 Kotlin 中调用具有泛型类型的方法
【发布时间】:2019-04-01 21:26:42
【问题描述】:

我有以下用Java编写的接口方法定义:

<T extends View & ISpecificView> T getSpecificView();

基于 Java 的消费者代码可以简单地通过调用该方法并将返回值视为扩展 View 类并通过以下方式实现 ISpecificView 接口的对象来操作此方法:

getContainer().getSpecificView().whateverTclassMethod()

尝试在 Kotlin 中调用相同的代码时,我在 getSpecificView() 方法上收到了 Type inference failed: Not enough information to infer parameter T (...) Please specify it explicitly 错误。 我很想明确地提供类型,但我无法传递任何特定的类,因为它可能是实现ISpecificView 接口的View 类的任何祖先。传递单个 ViewISpecificView 无济于事 - 它会导致 Type argument is not within its bounds. Expected: View! Found ICustomView ,反之亦然。

在调用方法时是否有可能在 Kotlin 中传递与 Java 的 T extends View &amp; ISpecificView 等效的值,以便我可以使用它?

【问题讨论】:

  • 顺便说一句,这比我想象的要难。至少就我的 Kotlin 知识而言
  • 我还认为将 Java 代码转换为 Kotlin 会很简单,但如果您有很多抽象,它会变得非常复杂。

标签: java android generics kotlin interface


【解决方案1】:

回顾一下(我希望我的问题是对的!),在 Java 中你可以做到

final View view = getContainer().getSpecificView();  // or
final ISpecificView iview = getContainer().getSpecificView();

在 Kotlin 中也是这样

val view: View = getContainer().getSpecificView()

结果为@​​987654324@


经过 50 分钟的尝试和尝试...
只需创建一个虚拟class(抽象?)

abstract class KView : View(), ISpecificView

并使用它来显式设置通用返回类型

val view: View = getContainer().getSpecificView<KView>()
view.whateverClassMethod()

val iview: ISpecificView = getContainer().getSpecificView<KView>()
iview.whateverInterfaceMethod()

// or just

(getContainer().getSpecificView<KView>() as View).whateverClassMethod()
(getContainer().getSpecificView<KView>() as ISpecificView).whateverInterfaceMethod()

需要对ViewISpecificView 进行特定转换,因为如果你只是这样做

getContainer().getSpecificView<KView>()

你会得到

class your.package$ExtendingClass cannot be cast to class your.package.KView

不过没关系。
即使在 Java 中,您也需要决定是要 View 还是 ISpecificView


这样你就可以对ViewISpecificView的所有方法进行操作了。


真的,我不知道还能尝试什么。希望有人想出更好的东西。

编辑:如果你的意思是在 Java 中,你会这样做

final ExtendedView ev = getContainer().getSpecificView();

好吧,恕我直言,这有点错误,即使它编译,因为你不能保证返回类型真的是ExtendedView。你肯定知道它扩展了View 并实现了ISpecificView

【讨论】:

  • 这看起来很有希望,但是比通用解决方案有点hacky - 如果我必须处理这样的几种情况,我需要为我需要结合的每个接口创建一个新的抽象类View 类。会检查出来。为调用者简单地提供类似&lt;View &amp; ISpecificView&gt; 的东西还是不错的。也许这应该是 Jetbrains 的新票?
  • @mrpasqal 随时回答discuss.kotlinlang.org/t/…
  • @mrpasqal 我用更精确的代码更新了答案。
  • 好收获。这很有帮助。由于没有更优雅的解决方案,我将其标记为可接受的答案。不是很优雅,但很有效。看起来 Kotlin sill 必须改进。感谢您对@LeppEdd 的支持!
【解决方案2】:

您应该能够使用以下方法实现此目的:

fun <T> getSpecificView() where T : View, T : ISSpecificView {}

可以在here找到相关文档。

【讨论】:

  • 声明部分是这样,但我在调用方需要这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
相关资源
最近更新 更多