为了账号安全,请及时绑定邮箱和手机立即绑定

Java泛型和Scala的交集是...进展不顺利

Java泛型和Scala的交集是...进展不顺利

慕后森 2022-09-22 16:05:33

我坦率地承认,我在这里有点超出我的深度。我在类型系统上的正式培训已经过去了几十年。我在Java中相当琐碎地使用了一两次泛型,但它们并不是我可以声称对它们有深刻而透彻的理解的东西。我也是Scala的新手,所以我也不是说对它的类型系统有深入或透彻的了解。


我开始更新我的XML葫芦v2实现,用Scala(今天的2.12)编写,使用Saxon 9.9。Saxon 9.9在许多地方引入了泛型。我很好。我能应付,我想象。


除了,我显然不能。


绊脚石是尝试实现一个扩展扩展函数定义类的类。它有一个内部类,用于扩展函数调用类。反过来,它具有一个抽象方法,调用,在Java中如此定义:


public abstract Sequence<?> call(

    XPathContext context,

    Sequence[] arguments

)

我第一次尝试在Scala中定义这一点是:


override def call(

    context: XPathContext,

    arguments: Array[Sequence]

): Sequence[_]

但这不会编译:“特征序列采用类型参数”。


这是真的:


public interface Sequence<T extends Item<?>>

(顺便说一句,项目是:


public interface Item<T extends Item<?>>

extends GroundedValue<T>

由于其他原因,我发现这有点令人困惑)


对于我的第二次尝试,我尝试了:


override def call(

    context: XPathContext,

    arguments: Array[Sequence[_]]

): Sequence[_]

但是,我被告知,这并不能覆盖任何东西。哈克,编译器说:


[error] (Note that Array[net.sf.saxon.om.Sequence]

does not match Array[net.sf.saxon.om.Sequence[_]]:

their type parameters differ)

在这里,我们似乎陷入了僵局。当然,我可以在Java中实现该死的东西,但这是Scala或我的理解中的实际限制吗?


顺便说一句,我之前就在我的第一次尝试中撒谎。我的第一次尝试实际上是:


override def call(

    context: XPathContext,

    arguments: Array[Sequence[_ <: Item[_ <: Item[_]]]]

): Sequence[_ <: Item[_ <: Item[_]]]

我通过直言不讳地将Java复制到斯卡拉并让IntelliJ IDEA翻译它来制作。我未能弄清楚如何处理项目声明的递归性质。


查看完整描述

3 回答

?
隔江千里

TA贡献1557条经验 获得超10个赞

尝试

override def call(context: XPathContext, arguments: Array[Sequence[_ <: Item[_]]]): Sequence[_] = ???


查看完整回答
反对 回复 5天前
?
UYOU

TA贡献1539条经验 获得超4个赞

这绝对是编译的(从而证实了德米特罗·米廷的提议是有效的):


// ExtensionFunctionCall.java

public interface ExtensionFunctionCall {

  Sequence<?> call(String ctx, Sequence[] args);

}


// Item.java

public interface Item<T extends Item<?>> {}


// Sequence.java

public interface Sequence<T extends Item<?>> {}


// Impl.scala

class Impl extends ExtensionFunctionCall {

  override def call(

    ctx: String,

    args: Array[Sequence[_ <: Item[_]]]

  ): Sequence[_] = ???

}

顺便说一句,这不仅仅是斯卡拉的问题。如果你忘记了Scala一秒钟,并尝试在Java中实现它,你得到的基本上是相同的错误:


class ImplJava implements ExtensionFunctionCall {

  public Sequence<?> call(

    String ctx,

    Sequence<?>[] args

  ) {

    return null;

  }

}

给:


ImplJava.java:1: error: ImplJava is not abstract and does not override abstract method call(String,Sequence[]) in ExtensionFunctionCall

class ImplJava implements ExtensionFunctionCall {

^

ImplJava.java:2: error: name clash: call(String,Sequence<?>[]) in ImplJava and call(String,Sequence[]) in ExtensionFunctionCall have the same erasure, yet neither overrides the other

  public Sequence<?> call(

                     ^

2 errors

现在,这真的很神秘,我不知道如何在Java中写下这种类型。我不确定它是否可以在Java中表达而不恢复到1.4风格。事情是邪恶的,或者,引用德米特罗·米廷链接的这篇精彩文章:Sequence[]


原始类型很糟糕。停止使用它们


查看完整回答
反对 回复 5天前
?
拉丁的传说

TA贡献1430条经验 获得超8个赞

我认为在java中没有类型参数可以转换为最高可能的超类型(在这种情况下)。所以,我希望这样的东西能起作用:SequenceSequence[Foo]FooItem

override def call(context: XPathContext, arguments: Array[Sequence[Item[_]]]): Sequence[_] = ???



查看完整回答
反对 回复 5天前

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信