2017-07-01 4 views
0

単純な共分散の例:asInstanceはなぜ機能しますか?Scala:このおもちゃの共変例をどのように働かせるか?

class Fruit(name: String) { def get_name = name} 
class Apple(name: String) extends Fruit(name) 
class Orange(name: String) extends Fruit(name) 
class BigOrange(name:String) extends Orange(name) 

    // Contrived but simple covariant box with some utility functions 
    class Box[+T <: Fruit] { 
    def foo[ U >: T] (item: U): String = item.asInstanceOf[T].get_name 
    } 

    val f = new Fruit("fruit") 
    val a = new Apple("apple") 
    val o = new Orange("orange") 

    // Error. Makes sense apples cannot be casted to oranges 
    println(a.asInstanceOf[Orange]) 


    val bo1 = new Box[Orange] 
    println(bo1.foo(a)) // Returns Apple ! How was an apple seemingly casted to an orange? 

なぜ最後の行は機能しますか?渡されたリンゴがオレンジ色にキャストされるようにロジックに問いませんか?

2番目の質問:なぜこのコードでget_nameが認識されないエラーを出すのですか?そしてU>:[フルーツ+ T <]:間

class Box[+T <: Fruit] (item: T) { 
    val contents = item 
    def foo[ U >: T] (item: U): String = item.get_name 
} 

Tは、アイテムがget_nameを持っている必要があること、それは明らかis'nt?なぜエラー?

+0

あなたが 'asInstanceOf'を使う必要があるときは、それはあなたが何か間違っていることを示すものです。 'foo'が宣言される方法は' foo(1200) 'や' foo( "bar") 'のように呼び出すことができます。私はそれがあなたが望むものだとは思っていません...しかし、あなたが実際に望んでいるものは何ですか?ここでは正確に何をしようとしていますか?たとえば、 'def foo(item:T)= item.get_name'で始めるのはなぜですか? – Dima

+0

私は何かがなぜ機能するのか自分に尋ねて学びたいと思っています。いいえ、foo(120)は機能しません。 – user7938511

+0

「作品」とは、コンパイルすることを意味します。 typeパラメータは無用です。この関数は任意の時刻のパラメータを受け入れ、実行時に例外をスローします。 Scalaは厳密に型指定された言語ですが、これはどのように使用されるべきではありません。 – Dima

答えて

1

[+ T <:Fruit]とU>:Tの間にアイテムにget_nameがあることは明らかですか?

もちろんそうではありません。たとえば、U = Anyは制約を満たし、get_nameのメンバーはありません。

+0

1. U>の行に沿って拘束する方法はありますか?T _and_ U!=任意の_と_ U <:果物?もしそれがあれば、それは将来可能でしょうか? – user7938511

+0

'U>:T'と' U <:Fruit': 'U <: Fruit >:T'を組み合わせることができます。そして、 'U <:Fruit'はすでに' U!= Any'を意味しています。 –

1

asInstanceOf[T]タイプTBoxであるため、実際には何もしません。また、コンパイラから警告を受ける必要があります。

1

問題がここに...

class Box[+T <: Fruit] (item: T) { 
    val contents = item 
    def foo[U >: T] (item: U): String = item.get_name 
} 

...あなたが別で1 itemをシャドウイングしていることです。第1のitem: T,にはget_nameというメンバーがありますが、第2のitem: Uは認識できません。 Fruitの親クラスまたはスーパークラスである可能性があります。つまり、get_nameメンバーの保証はありません。

関連する問題