1

我正在尝试:::使用List. 好的,在 REPL 中输入两个列表并查看发生了什么之后,我知道它现在在做什么。但是 ::: 方法的 API 定义很难阅读和理解。我只是通过阅读它“返回”来“得到它”。

def :::[B >: A](prefix: List[B]): List[B]
    Adds the elements of a given list in front of this list.
    prefix  The list elements to prepend.
    returns list resulting from the concatenation of the given list prefix and this list.
    Example:  List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)

特别是这部分是什么意思:[B >: A](prefix: List[B])。我的意思是我能够通过阅读方法返回的内容并使用它来理解方法返回的内容。对于未来,我希望能够阅读不同方法的 API 并尝试理解所有内容。这就是我问这个问题的原因。

4

3 回答 3

4

[B >: A]意味着该方法是泛型的,并且采用一个称为的类型参数B,该参数必须是A. (prefix : List[B])意味着它需要一个名为prefixtype 的实际参数List[B]

于 2012-10-15T21:53:55.513 回答
2

如果不是为了子类型,这将被编写def :::(prefix: List[A]): List[A],那么[B >: A]只是让你,比如说,将 a 前缀List[Animal]到 a 上List[Cat],得到一个更大的List[Animal]

于 2012-10-15T22:21:36.557 回答
1

这两个答案都是正确的。您只需要记住这A是您当前列表的类型参数,并且B是您提供给的列表的类型参数:::

如果你还没有信心,可以试试自己定义的List

  class MyList[+A]{
    def :::[B >: A](prefix: MyList[B]): MyList[B] = new MyList[B]()
  }

  class Animal
  class Dog extends Animal
  class Pig extends Animal
  class Rock 

现在您可以在 REPL 中进行测试:

scala>  new MyList[Dog]
res0: Test.AkkaTest.MyList[Test.AkkaTest.Dog] = Test.AkkaTest$MyList@190a0d51

scala>  new MyList[Pig]
res1: Test.AkkaTest.MyList[Test.AkkaTest.Pig] = Test.AkkaTest$MyList@1db5d2b2

scala>  res0:::res1
res2: Test.AkkaTest.MyList[Test.AkkaTest.Animal] = Test.AkkaTest$MyList@25927275

scala>  new MyList[Rock]
res3: Test.AkkaTest.MyList[Test.AkkaTest.Rock] = Test.AkkaTest$MyList@49f85a86

scala>  res3:::res0
res4: Test.AkkaTest.MyList[ScalaObject] = Test.AkkaTest$MyList@42130c2

scala>  res0:::res3
res5: Test.AkkaTest.MyList[ScalaObject] = Test.AkkaTest$MyList@6f24d504

所以你应该知道 ::: 连接两个列表并创建一个泛型类型是第一个共同祖先的列表。这是因为类型列表是协变的,所以例如你可能会认为,在 res3 和 res0 的情况下,编译器会执行以下操作:

  • A 是 Rock B 是 Dog,B 不是 A 的父类,也许我应该抛出编译器错误?
  • 但由于 MyList 是协变的,MyList[Dog] 是 MyList[ScalaObject] 的子类。
  • 酷,ScalaObject 是 Rock 的父类,所以我将创建一个 ScalaObject 列表
于 2012-10-16T09:51:01.960 回答