0

String を型にキャストすると、Any自動的にString--Why?と見なされなくなります。次の例を参照してください。

val str = "foo"
val strAsAny = "bar".asInstanceOf[Any]
def f1(x: String) = println(x.toString)
def f2(x: Any) = println(x.toString)

f1(str) // works, type exactly given
f2(str) // works, subtype of Any given

f1(strAsAny) // works not, but strAsAny.isInstanceOf[String] = true !
f2(strAsAny) // works, type exactly given

両方の値がまだタイプを持っているので、これは少し混乱しますString:

scala> str.isInstanceOf[String]
res4: Boolean = true

scala> strAsAny.isInstanceOf[String]
res5: Boolean = true

私の推測では、interhitance-chain の「上に移動するための」型変換のみが自動的に行われるということです。これは正しいです ?

4

2 に答える 2

5

型は、実際に取得したものではなく、期待するものを指定します。そのスロットには、期待どおりのものを何でも配置できます。

ではAny、ほとんど期待しないので、何でもうまくいきます。では、、、などStringを期待しlengthますcharAt。したがって、aStringは an の要件を満たすことができますが、Anyその逆はできません。たまたまスロットに a を入れた場合String、できることを約束しているだけなので、その値を取って a を期待するものに渡すことはできません。AnyAnyString

これはLiskov Substitution Principleと呼ばれ、(安全な) オブジェクト指向設計の基本原則です。

于 2012-07-04T18:54:51.170 に答える
3

static 型dynamic 型を混同しています。

静的型は、コンパイラが知っているものであり、コンパイル時に存在するものです。

つまり、これを行うと:

val strAsAny = "bar".asInstanceOf[Any]

strAsAny次に、コンパイラは type を持っていることを認識 (または考え)Anyます。Stringそこに保存されていることはわかりません。

可能な限り避けてください。最も有効な使用法は、型の割り当て ( ) またはパターン マッチング ( )asInstanceOfに置き換えることができ、どちらも安全です。演算子は、それが間違っていることを知っていても、コンパイラが知っていることを無視し、あなたが言っていることを信じるようにコンパイラに指示するため、安全ではありません。"bar" : Anycase anyAsStr: String => "got a String"asInstanceOf

そのため、asInstanceOfほとんどがコンパイル時の演算子ですが、JVM が実行するコードもいくつか生成します。

ここで、コンパイラは呼び出し可能であると認識しているメソッドのみを呼び出すことができるため、コンパイラが考えることが重要です。そのため、実行時strAsAnyが含まれていてStringも、コンパイラはそれを知りません。それが であることを忘れるように指示しました"bar"が、Stringそうしました。したがって、その上でメソッドを呼び出すことはできませんString

一方、動的型は実行時に trueです。ほとんどの場合、Scala のような言語の場合、コンパイラーは実行時に何が真であるかどうかを知る方法がありません。

そして、コンパイラが何かを知ることができるかどうかisInstanceOfは、実行時の操作です。コンパイラは、何が起こるかについて何も言いません。

したがって、これを行うと:

strAsAny.isInstanceOf[String]

コンパイラは気にしません。コードをコンパイルするだけです。コードを実行するstrAsAnyと、JVM は 内に格納されている値の種類を確認し、それが実際に であることを確認してから、Stringを返しtrueます。

于 2012-07-04T21:15:08.090 に答える