2016-10-01 5 views
2

以下のタイプTはサブタイプFruitです。 AppleもサブタイプFruitです。だから、コンパイラは、なぜタイプの帰納法が以下で使われるとき、AppleをTに強制しないのですか?なぜそれを動作させるために明示的なキャスティングが必要なのですか?タイプを推論するときの強制のルールは何ですか?サブタイプと型変換

trait Fruit 
case class Apple(id: String) extends Fruit 

type T <: Fruit 

val t: T = Apple("apple") // why doesn't the compiler coerce Apple to T? 

val t: T = Apple("apple").asInstanceOf[T] // works! 

答えて

1

これを少し簡略化しましょう。梨と果実を胎児と交換する。

trait Fetus 
class Apple extends Fetus 
type Pear <: Fetus 

val t: Pear = new Apple() 

私たちはFetusと宣言し、「AppleはFetus」と言い、「PearはFetus」です。 これまでのロジックは正しいです。しかし、それから、「リンゴを梨の箱に入れる」ことを試みます。そしてここに私たちの間違いがあります。

のは、別の例を考えてみましょう:

ここ
trait Fetus 
class Apple extends Fetus 
type Fruit >: Apple <: Fetus 

val t: Fruit = new Apple() 

我々は、胎児を宣言した後、私たちは、「Appleが胎児である」と述べた後、私たちは「フルーツは、Appleと胎児の間の中間にあるものだ」と述べました。つまり、Fetus - > Fruit - > Appleの階層構造を構築しました。だから、アップルはフルーツのサブタイプで、あなたは「果物の箱にリンゴを入れる」ことができます。

UPDATE:猫は、彼らは両方の動物であるのにもかかわらず、犬にはできませんように

Pearは間違いなく、可能とAppleすることはできません。水平ではなく垂直方向にのみ階層で移動できます:

Creature 
    | 
Animal 
    _|_ 
/ \ 
Dog Cat 
     \ 
     White Cat 
+0

したがって、 'Pear <:Fetus'はPearが' Fetus'の** specific **サブタイプであり、** specific **サブタイプが 'Apple'でないことを意味しますか?しかし、なぜ「梨」は「アップル」ではないのですか?コンパイラが知っていることは、 'Pear'が' Fetus'のサブタイプであることです。アップルでも、アップルでもないかもしれません。 – Samar

+0

私は答えを –

+0

あなたの答えをありがとう、それは今意味があります。 – Samar

1

私はあなたが定義 type T <: Fruitの意味を混乱していると思う:それは(type T = Fruitとは異なりタイプの別名である)抽象型 defintionです。 Absract型はFruitを拡張するクラスTを作成するのではなく、抽象宣言であり、使用するいくつかのサブクラスでオーバーライドする必要があります。 Learning Scala, chapter 10から

は...抽象型は、ゼロ、1、または多くのクラスに解決することができる仕様です。彼らは別名を入力する同様の方法で動作しますが、されて仕様が、彼らは抽象的であり、インスタンスに宣言type T <: Fruitが唯一のクラス/トレイト(オブジェクトではなく、またトップに常駐できること

お知らせを作成するために使用することはできませんそのクラス/特性が拡張されるまで無意味であるからです。それが定義されているところではまだ抽象的なので、コンパイラはAppleがそれを拡張していることを確実に知ることができません。

ような定義を使用するための例:ここでは

trait Price { 
    type T <: Fruit 
    def printPrice(x: T): Unit 
} 

class ApplePrice extends Price { 
    override type T = Apple 
    override def printPrice(x: Apple): Unit = ??? 
} 

ApplePriceは何かでこの抽象型をオーバーライドする必要があります。 Priceの別のサブクラスはPriceに配置された表現val t: T = Apple("apple")がコンパイルできないということを明確にすべきである(例えばBanana extends Fruit)別の何か、でこれを上書きしてしまうことがあります - いくつかの可能な拡張クラスに対して、TAppleではなく、またAppleTを延長ありません。

+0

「抽象型」と「型別名」を指摘してくれてありがとう。しかし、抽象型は一見型付き型として使うことができます(抽象型はクラスを暗示していると似ていますか?)また、ドミトリーの推論はどう思いますか?直感的に思える。 – Samar

+1

ドミトリーの答えは完全に正しいです。私は、抽象定義の性質が明確化を必要とする問題であると仮定しました。結局のところ、両方の答えが一緒になって完全な画像を与えます。つまり、抽象的で、T _might_型は「Apple」のスーパータイプではないタイプなので、コンパイラーは「Apple」を割り当てることができません。 –

+0

コンパイラは、 'T 'が' Apple'のスーパータイプであれば 'T'をタイプするよう強制することができました。 'T'は' Apple'のサブタイプであるかもしれないし、実際には言及されていないDimitryのように水平に置かれているので、それは成り立たない。ありがとう、それはすべて意味が今! – Samar