4

Scalasホームページから取得したListNodeの例は、次のようになります

case class ListNode[+T](h: T, t: ListNode[T]) {
  def head: T = h
  def tail: ListNode[T] = t
  def prepend[U >: T](elem: U): ListNode[U] =
    ListNode(elem, this)
}

このクラスを使用すると、次のようなオブジェクトを作成できます。

val empty: ListNode[Null] = ListNode(null, null)
val strList: ListNode[String] = empty.prepend("hello")
                                     .prepend("world")
val anyList: ListNode[Any] = strList.prepend(12345)

ご覧のとおり、ノードの前に整数値を追加できStringます。メソッドに整数が与えられると、typeパラメーターUが自動的にに設定されるため(のスーパータイプではないため) 、これは機能すると思います。AnyprependIntString

独自の下限の例でこれを試すと、エラーが発生します。

scala> class E[T >: String]
defined class E

scala> new E[Any]
res1: E[Any] = E@135f0a

scala> new E[Int]
<console>:11: error: type arguments [Int] do not conform to class E's type param
eter bounds [T >: String]
      val res2 =
          ^
<console>:12: error: type arguments [Int] do not conform to class E's type param
eter bounds [T >: String]
              new E[Int]
                  ^

ここのタイプが例のようにInt自動的にタイプとして表示されないのはなぜですか?AnyListNode


更新1:これも機能します(新しいListNodeタイプはタイプである必要があると明示的に言わずにAny

scala> val empty: ListNode[Null] = ListNode(null, null)
empty: example.listNode.ListNode[Null] = ListNode(null,null)

scala> empty.prepend("hello").prepend("world")
res0: example.listNode.ListNode[java.lang.String] = ListNode(world,ListNode(hell
o,ListNode(null,null)))

scala> val strList: ListNode[String] = empty.prepend("hello").prepend("world")
strList: example.listNode.ListNode[String] = ListNode(world,ListNode(hello,ListN
ode(null,null)))

scala> strList.prepend(12345)
res1: example.listNode.ListNode[Any] = ListNode(12345,ListNode(world,ListNode(he
llo,ListNode(null,null))))
4

2 に答える 2

7

Intはのスーパータイプではないため、上記のエラーが発生しますString

ListNode上記のコードでStringは、は(クラス階層Nullを参照)のスーパータイプであり、(正しく指摘したように)のスーパータイプであることに注意してください。AnyString

混乱は、実際には同じではない2つの操作を比較することによって引き起こされると思います。new E[Int]つまり、クラスを型パラメーターIntでインスタンス化します。これは、下限に準拠していないStringため、失敗します。

一方、上記のListNodeコードprependでは、のスーパータイプをとるメソッドをU呼び出しますT。を作成するときanyList、これはとの唯一の一般的なスーパータイプであるため、 U(あなたが推測したように)解決されます。したがって、実際にはに渡さないものと考えることができますが、 (これもたまたまタイプです)の任意のインスタンスです。)。AnyStringIntIntAnyInt

したがって、

val anyList: ListNode[Int] = strList.prepend(12345)

strList.prepend(12345)を返すことしかできないので、同様に失敗しますListNode[Any]

于 2012-07-01T09:26:26.137 に答える
1

あなたは根本的に異なる1つのことをしています:Int型を渡すことです。例として、元のコードを壊してみましょう。

scala> val anyList: ListNode[Any] = strList.prepend[Int](12345)
<console>:11: error: type arguments [Int] do not conform to method prepend's type parameter bounds [U >: String]
       val anyList: ListNode[Any] = strList.prepend[Int](12345)
                                                   ^

見る?を指定すると壊れますタイプとしてではなくタイプとして推測されIntたため、元のバージョンで機能しました。12345AnyInt

于 2012-07-01T17:40:56.987 に答える