【问题标题】:Generics in Scala: implementing an interface/trait twice?Scala中的泛型:两次实现接口/特征?
【发布时间】:2011-11-25 19:29:00
【问题描述】:

给定一个通用接口,如下所示

interface I<T> {
    void m(T t);
}

我可以在 C# 中创建一个实现 I 两次(或更多)的类,并为 T 提供不同的类型,例如

class C : I<int>, I<String> {
   public void m(int i) { }
   public void m(String s) { }
}

由于泛型类型信息的擦除,这在 Java 中无法完成,但在 Scala 中可以实现这样的事情吗?

【问题讨论】:

  • 你能用 Scala 代码描述你想做什么。这里很多人不熟悉C#。
  • 好吧,我对 Scala 不是很熟悉(正在努力学习 :))。但是,上面的代码对于任何了解 Java 的人来说应该很容易理解,只要您知道此设置中“class C”后面的“:”在 Java 语言中表示“实现”即可。我在 Scala 中尝试过的是将 I 变成一个 trait(只需将“interface”替换为“trait”),然后将 C 定义为“class C extends I with I { ...”,但是这不起作用。
  • 在 Scala 中,泛型类型包含在 [] 中,因此您可以使用 I[Int]I[String] 来执行此操作。您是否尝试过在声明中使用ClassManifest
  • 啊,我知道,<...> 只是一个错字。我将使用 ClassManifest 做什么?
  • 请注意,Scala 编译为普通 Java 字节码,因此如果“由于擦除泛型类型信息而无法在 Java 中完成”,那么同样适用于 Scala(尽管公平地说 Scala 确实得到了围绕 JVM 在编译器方面的一些限制)。

标签: c# java generics scala


【解决方案1】:

不,它不能。通常我在这种情况下所做的是

class C {
  object IInt extends I[Int] { ... }
  object IString extends I[String] { ... }
  ...
}

【讨论】:

    【解决方案2】:

    没有。只有在 Scala 中混合相同的 trait 是可能的,如果 trait(接口)被参数化的 2 种类型彼此 conform 并且该 trait 没有两次混合到同一个类中 直接。为了确保这两种类型相互一致,您通常必须使类型参数协变 (+)。

    例如,这是不允许的:

    scala> trait A[+T] { def foo: T = sys.error() }
    defined trait A
    
    scala> class C extends A[AnyRef] with A[String]
    <console>:8: error: trait A is inherited twice
           class C extends A[AnyRef] with A[String]
    

    但这是:

    scala> trait A[+T] { def foo: T = sys.error() }
    defined trait A
    
    scala> class C extends A[AnyRef]
    defined class C
    
    scala> class B extends C with A[String]
    defined class B
    

    请注意,在这种情况下,您不会像 C# 那样获得 overloading 语义,而是获得 overriding 语义 - A 中的所有方法都带有符合要求的签名将被融合到具有最具体签名的一种方法中,根据linearization rules 选择方法,而不是每次混合特征时都使用一种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多