2

重複の可能性:
Scala: 抽象型とジェネリック

「プログラミング in Scala」の第 20.6 章「抽象型」では、抽象型の使用について、次の結果コードで終わる例で説明しています。

class Food
abstract class Animal {
  type SuitableFood <: Food
  def eat(food: SuitableFood)
}

class Grass extends Food
class Cow extends Animal {
  type SuitableFood = Grass
  override def eat(food: Grass) {}
}

これらの定義では、 のオブジェクトはCow魚を食べることができません。

class Fish extends Food
val bessy: Animal = new Cow
bessy eat (new Fish) // Error, type mismatch

抽象型の使用に関するこの良い例を読んだ後、なぜ代わりに型パラメーターを使用しないのか疑問に思いました。

class Food
abstract class Animal[T <: Food] { 
  def eat(food: T)
}

class Grass extends Food
class Cow extends Animal[Grass] {
  override def eat(food: Grass){}
}

class Fish extends Food
val bessy: Animal[Grass] = new Cow
bessy eat (new Fish) // Also ends in a type mismatch error !

ここで抽象型の代わりに型パラメーターを使用する違いはどこにありますか?

4

1 に答える 1

2

Martin Odersky は、このインタビューでその質問に答えました。

抽象化には常に、パラメーター化と抽象メンバーという 2 つの概念がありました。Java にも両方がありますが、抽象化している対象によって異なります。Java には抽象メソッドがありますが、メソッドをパラメーターとして渡すことはできません。抽象フィールドはありませんが、値をパラメーターとして渡すことができます。同様に、抽象型メンバーはありませんが、型をパラメーターとして指定できます。したがって、Java でもこれら 3 つすべてを使用できますが、どの抽象化原理をどのような種類のものに使用できるかについては違いがあります。そして、この区別はかなり恣意的であると主張することができます.

私たちが Scala で行ったことは、より完全で直交することでした。3 種類のメンバーすべてに同じ構造原則を適用することにしました。したがって、抽象フィールドと値パラメーターを使用できます。メソッド (または「関数」) をパラメーターとして渡すことも、それらを抽象化することもできます。タイプをパラメーターとして指定するか、それらを抽象化できます。そして、概念的に得られるのは、一方を他方の観点からモデル化できるということです。少なくとも原則として、あらゆる種類のパラメータ化をオブジェクト指向の抽象化の形式として表現できます。したがって、ある意味では、Scala はより直交的で完全な言語であると言えます。

とはいえ、両者には微妙な違いがいくつかありますが、頭の中で思い出すことはできません。

このスレッドも参照してください。

于 2012-06-29T19:31:45.503 に答える