【问题标题】:Pass subclass of class as type parameter (type parameter is subclass)将类的子类作为类型参数传递(类型参数是子类)
【发布时间】:2021-02-13 04:41:29
【问题描述】:

让我们考虑一下:

public class Text extends BinaryComparable
    implements WritableComparable<BinaryComparable> {

我们可以看到Text 是 BinaryComparable。

那么,让我们考虑

@InterfaceAudience.Public
@InterfaceStability.Stable
public interface WritableComparable<T> extends Writable, Comparable<T> {

我有一些 Scala 课程:

trait MyClass[A <: WritableComparable[A]] {

无法创建

MyClass[Text] = new MyClass[Text]()

由于类型不匹配。为什么?毕竟Text就是BinaryComparable怎么解决呢?

【问题讨论】:

  • MyClass 只带一个参数,你又会遇到哪个错误?

标签: java scala generics scala-java-interop f-bounded-polymorphism


【解决方案1】:

WritableComparable[BinaryComparable] 与WritableComparable[Text] 不同或不是其超类型,因为WritableComparable 在T 中是不变的(Java 泛型实际上没有协变或逆变)。

如果WritingComparable 被声明为trait WritingComparable[-A],那么它就是compile。

不过,您的最后一个代码 sn-p 没有多大意义,因为 MyClass 不采用 2 个类型参数(如 Luis Miguel Mejia Suarez 所述)。你不应该得到类型不匹配错误,它应该告诉你参数太多。我想你的意思只是MyClass[Text]。

Here 是一个关于不变性、逆变性和协变的问题。

【讨论】:

  • 我编辑了它。能告诉我,怎么修吗?有可能吗?
  • @tomek.xyz 我尝试使用[_ &gt;: A],但使用doesn't work。 existential type 可能有效,但它很hacky,如果您对MyClass 的类型参数有任何控制权,我真的建议您重新考虑您的设计。
【解决方案2】:

你可以尝试多加一个类型参数

trait MyClass[B >: A, A <: WritableComparable[B]]

val mc: MyClass[BinaryComparable, Text] = new MyClass[BinaryComparable, Text] {}

与trait MyClass[A &lt;: WritableComparable[_ &gt;: A]]相反,这不会产生illegal cyclic reference。

或者,您可以将MyClass 中的边界定义为

trait MyClass[B, A <: B with WritableComparable[B]]

val mc: MyClass[BinaryComparable, Text] = new MyClass[BinaryComparable, Text] {}

您甚至可以使用存在类型排除 B(如 @user 建议的那样)

trait MyClass[A <: B with WritableComparable[B] forSome { type B }]

val mc: MyClass[Text] = new MyClass[Text] {}

此类存在类型将在 Scala 3 中被弃用

http://dotty.epfl.ch/docs/reference/dropped-features/existential-types.html

【讨论】:

  • 老实说,我并不完全理解。 A &lt;: WritableComparable[B] 保证A 有类似compare(T o) 的方法。 B &gt;: A 确实意味着 A extends B。为什么它保证A 可以与A 的所有supertypes 相媲美? (这里称为B)
  • 换句话说,它也应该适用于MyClass[B, A &lt;: WritableComparable[B]]。
  • 哦,我现在明白了。基本上,我们表示A 有方法compareTo(B o) 和B 是A 的超类型。这确实意味着我们可以比较:new A().compareTo(*) 其中 * 是任意对象,是A 的超类型实例。
  • @tomek.xyz 这只是Text extends BinaryComparable implements WritableComparable&lt;BinaryComparable&gt; 的概括。 Text 是 A,BinaryComparable 是 B。 Text extends... implements... 可以写成A &lt;: B with WritableComparable[B]。所以你可以介绍trait MyClass[B &gt;: A, A &lt;: WritableComparable[B]]或trait MyClass[B, A &lt;: B with WritableComparable[B]]。
猜你喜欢
  • 2013-02-16
  • 1970-01-01
  • 2019-02-27
  • 2021-02-12
  • 1970-01-01
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
相关资源
最近更新 更多