如何在 Scala 中扩展包含泛型方法的 Java 接口?

Posted

技术标签:

【中文标题】如何在 Scala 中扩展包含泛型方法的 Java 接口?【英文标题】:How do I extend Java interface containing generic methods in Scala? 【发布时间】:2010-12-01 03:13:14 【问题描述】:

假设我们有以下 Java 接口:

// Java
public interface Foo 
    <T> T bar(Class<T> c);

我应该如何在 Scala 中扩展它?写作

// Scala
class FooString extends Foo 
  override def bar(c: Class[String]): String = "hello, world";

将导致编译器抛出“类 FooString 需要是抽象的,因为类型为 [T](Class[T])T 的特征 Foo 中的方法 bar 未定义。”

提前致谢!

更新: 丑陋的事实是:我误解了 Java 中的泛型。

无论如何,尼古拉斯和沃尔特的回答都显示了我的困境的解决方案,尽管我更喜欢沃尔特的回答,因为它不那么冗长。

【问题讨论】:

你终于明白了!很高兴你已经理解了你在泛型上的错误。不客气。 【参考方案1】:

你可以这样改变:

public interface Foo<T> 
    T bar(Class<T> c);


class FooString extends Foo[String] 
    override def bar(c: Class[String]): String = "hello, world";

【讨论】:

其实Java接口是第三方API,所以我只好照原样使用。 据我所知,没有办法用特殊类型的方法覆盖泛型方法。【参考方案2】:

这行得通:

class FooString extends Foo 
  def bar[String](c: Class[String]): String = "hello world".asInstanceOf[String]


val fs = new FooString
println(fs.bar(classOf[String]))

已编辑:

@Eastsun 的 cmets 是正确的。由于 bar 是带有类型参数 T 的泛型方法,因此在 Scala 中 bar 的实现也必须是泛型方法。我认为在 Scala 中实现 Foo 的正确方法如下:

class FooString extends Foo 
  def bar[T](c: Class[T]): T = c.newInstance.asInstanceOf[T] // c gotta have a default constructor


val fs = new FooString
println(fs.bar(classOf[String]).getClass) // prints "class java.lang.String"
println(fs.bar(classOf[java.util.Date]).getClass) // prints "class java.util.Date"

【讨论】:

实际上,它并没有像您预期的那样工作。 FooString#bar 方法中的“String”不是 java.lang.String 类型,而是 Foo 中的“T”类型参数。因此,您可以编写 fs.bar(classOf[Int]) 之类的内容并编译 OK,但运行时出现异常。【参考方案3】:

它不起作用,因为您没有正确实现接口。您的方法 n scala 的签名必须是:

def bar[T](c:Class[T]):T

只有当你想要 ton 实现 Foo 时,你才能修复 String 的行为。

第三次尝试,根据我们的讨论:

def bar[T](c:Class[T]):T = 
  // Some stuff
  val o:Any = myUntypedFunction(env)
  c.cast(o)

myUntypedFunction 将根据上下文创建一个对象,然后您使用类参数转换您的结果并获得一个 T 对象。 再说一遍:这种行为在 java 和 scala 中是一样的。

【讨论】:

这是我的问题:如何使签名匹配? 你不能。您尝试更改界面,这不是scala问题,而是编程问题。接口说:“接受任何类并返回这个类的结果”,你的实现说“接受任何字符串类并返回一个字符串”。 bar 的实现必须使用 cast()、newInstance 或构造函数从对象 c 构建一个 T。 这只是一个人为的例子;我面临的实际问题需要我实现一个 Java 接口,该接口在方法中包含参数化类型,类似于我给出的示例。如果没有办法实现这一点,即使这可能是一个边缘情况,那么这是一个 scala 问题,因为它与 Java 不完全兼容。 我不认为这是一个 scala 问题。在 Java 中你无法做到这一点。 @shaolang:如果您认为这是一个 scala 问题,您能否给我们您的 FooString 类的有效 java 等效代码?我仍然相信您错过了 bar 函数中泛型声明的要点。

以上是关于如何在 Scala 中扩展包含泛型方法的 Java 接口?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin的类型具体化在Java或Scala中是不可能实现的?

Scala(或Java)中泛型函数的专业化

如何在泛型集合上创建扩展方法

Scala入门到精通——第十六节 泛型与注解

Scala的类与类型

Scala泛型