11

Scalaでは、分散はジェネリック型引数の+や-などの分散演算子で定義できます。たとえば、Listタイプは標準ライブラリでは共変です。

class List[+A]

したがって、共変リストを持つ関数は次のように定義できます。

def foo[A](list : List[A])

また、分散は一般的な境界でエミュレートできます。だから私たちもこれを書くことができます

def foo[A](list : List[_:< A])

もちろん、これは意味がありませんlist。すでに共変であるためです。しかし、共変ではない型に対しても同じトリックを行うことができます。(のようにStack)。もちろん、共変であるスタック(集約の継承)から新しいタイプを作成することもできます。

だから私の質問:

  1. 分散に一般的な境界を使用する必要があるのはいつですか?そして、いつ新しい共変型を作成する必要がありますか?
  2. 一般的な境界は分散にのみ役立ちますか、それとももっと宣言できますか(言語の概念)。
  3. それらが分散にのみ役立つ場合、境界はJavaとの互換性のためだけですか?

事前にt​​hx:)

4

2 に答える 2

14

タイプが自然に共変または反変である場合は、そのように宣言する必要があります。あなたのユーザーはそれをあなたに感謝するでしょう。使用場所の違いは、Javaが原因で実際​​にほとんど存在します。より正確には、のようなArray[T <: Number]タイプは、実存型の省略形として扱われます。

ArrayBuffer[T] forSome { type T <: Number }

Scalaでは、既存の型の構文はかなりかさばります。あまり使用しないことをお勧めしますので、これは意図的なものです。いつ実存型が必要になりますか?

  1. などのワイルドカードを使用してJavaタイプの類似物を記述しList<? extends Number>ます。
  2. のようなJavaraw型の類似物を書くことList

Javaでは、raw型とワイルドカード型はまったく同じではなく、どちらも実存型とはまったく同じではありません(それらが何でないかはわかっていても、正確に述べるのはかなり困難です)。しかし、それらは実際には実存主義に十分近いので、Scalaはそれらをこの種のタイプにマッピングすることをやめます。

于 2010-09-08T14:16:41.333 に答える
6
  1. Foo [T]などの新しいジェネリック型を作成するときは、その型が共変、反変、不変のいずれであるかを判断し、それぞれFoo [+ T]、Foo [-T]、またはFoo[T]と宣言する必要があります。確かに、これは少し難しいかもしれません。ただし、Fooのユーザーは、一般的な境界を使用してFooを使用する必要があるたびに、その決定を行う必要がなくなります。つまり、差異がタイプ自体のプロパティである場合は、呼び出しサイトの差異よりも宣言サイトの差異を優先します。

ところで、Martin Odersky、Lex Spoon、BillVennersによるProgrammingin Scalaの本には、分散についていくつかの素晴らしい説明があります。第19章タイプパラメータ化を参照してください。

于 2010-09-08T08:42:00.707 に答える