Scala 中的泛型:实现接口/特征两次?

发布于 2024-12-06 19:52:12 字数 326 浏览 0 评论 0原文

给定如下所示的通用接口,

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

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

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

由于擦除了通用类型信息,这在 Java 中无法完成,但可以类似这可以在Scala中实现吗?

Given a generic interface such as the following

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

I can in C# create a class that implements I twice (or more) with different types supplied for T, e.g.

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

This cannot be done in Java due to erasure of the generic type info, but can something like this be achieved in Scala?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拥抱没勇气 2024-12-13 19:52:12

不可以。在 Scala 中,只有当特征(接口)参数化为彼此一致的类型并且该特征不会两次混合到同一个类中时,才可能在 Scala 中混合相同的特征直接。为了确保这两种类型相互一致,通常必须使类型参数协变 (+)。

例如,这是不允许的:

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# 那样获得重载语义,而是获得重写语义 - A 中具有一致签名的所有方法将被融合到一个具有最具体签名的方法中,根据 线性化规则,而不是每次都使用一种方法已经混合了这个特性。

No. Mixing in the same trait is only possible in Scala if the 2 types with which the trait (interface) is parametrized with types that conform to each other and the trait is not mixed into the same class twice directly. To ensure that the 2 types conform to each other, you will generally have to make the type parameter covariant (+).

For example, this is not allowed:

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]

But this is:

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

Note that in this case you will not obtain the overloading semantics as is the case with C#, but the overriding semantics - all the methods in A with the conforming signature will be fused in one method with the most specific signature, choosing the method according to linearization rules, rather than having one method for each time you've mixed the trait in.

探春 2024-12-13 19:52:12

不,不能。一般来说,我在这种情况下所做的是

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

No, it can't. Generally what I do in this case is

class C {
  object IInt extends I[Int] { ... }
  object IString extends I[String] { ... }
  ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文