次のものがあると仮定します。
class B
class A extends B
trait T
その後、それは保持します:
val a: A with T = new A with T
a.isInstanceOf[B] // result is true !
isInstanceOf
メソッドは、サブタイプ関係の右側に一致する(すべてのタイプではない)少なくとも1つのタイプがあるかどうかをチェックするのは正しいですか?
一見すると、A with T
型の値はB
のサブタイプにはなり得ないと考えました。なぜならA
andT
はB
の両方のサブタイプではありません。しかし、それはA
ですまたはT
はB
のサブタイプです-そうですか?
isInstanceOf
は、継承チェーンに対応するエントリがあるかどうかを調べます。 A with T
のチェーンには、A
、B
、およびT
が含まれているため、a.isInstanceOf[B]
はtrueでなければなりません。
編集:
実際には、生成されたバイトコードはjavas instanceof
を呼び出すため、Javaではa instanceof B
になります。 a.isInstanceOf[A with T]
のようなもう少し複雑な呼び出しは(a instanceof A) && (a instanceof T)
になります。
一見すると、タイプAとTの値はBのサブタイプにはなり得ないと思った
ここには2つの誤解があります。まず、インスタンスの静的型はisInstanceOf
の結果に影響を与えます:なし。明確に言うと、a.isInstanceOf[B]
を実行するとき、a
がA with T
タイプであるという事実関係ない。
メソッドisInstanceOf
は、JVMによってバイトコードレベルで実装されます。クラス情報すべてのインスタンスが運ぶを見て、B
がクラスの1つ(インスタンス自体とその祖先のクラス)か、実装されたインターフェースの1つかをチェックします。それが「is-a」関係です。「a is a B」です。
技術的には、isInstanceOf
はJavaのリフレクションの一部であり、instanceof
として知られています。
2番目の誤解は、継承が何らかの形でremove親タイプになる可能性があることです。それは決して起こりません。継承は型を追加するだけで、削除することはありません。タイプA with T
は、A
、B
、T
、AnyVal
、およびAny
です。そのため、isInstanceOf
がA with T
型を見ても、trueを返します。