如何在 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 接口?的主要内容,如果未能解决你的问题,请参考以下文章