web-dev-qa-db-ja.com

「isInstanceOf」はどのように機能しますか?

次のものがあると仮定します。

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のサブタイプにはなり得ないと考えました。なぜならAandTBの両方のサブタイプではありません。しかし、それはAですまたはTBのサブタイプです-そうですか?

23
John Threepwood

isInstanceOfは、継承チェーンに対応するエントリがあるかどうかを調べます。 A with Tのチェーンには、AB、およびTが含まれているため、a.isInstanceOf[B]はtrueでなければなりません。

編集:

実際には、生成されたバイトコードはjavas instanceofを呼び出すため、Javaではa instanceof Bになります。 a.isInstanceOf[A with T]のようなもう少し複雑な呼び出しは(a instanceof A) && (a instanceof T)になります。

36
drexin

一見すると、タイプAとTの値はBのサブタイプにはなり得ないと思った

ここには2つの誤解があります。まず、インスタンスの静的型はisInstanceOfの結果に影響を与えます:なし。明確に言うと、a.isInstanceOf[B]を実行するとき、aA with Tタイプであるという事実関係ない

メソッドisInstanceOfは、JVMによってバイトコードレベルで実装されます。クラス情報すべてのインスタンスが運ぶを見て、Bがクラスの1つ(インスタンス自体とその祖先のクラス)か、実装されたインターフェースの1つかをチェックします。それが「is-a」関係です。「a is a B」です。

技術的には、isInstanceOfはJavaのリフレクションの一部であり、instanceofとして知られています。

2番目の誤解は、継承が何らかの形でremove親タイプになる可能性があることです。それは決して起こりません。継承は型を追加するだけで、削除することはありません。タイプA with Tは、ABTAnyVal、およびAnyです。そのため、isInstanceOfA with T型を見ても、trueを返します。

11