4

Scala は、Java の型システムに非常に洗練されたクラス階層を重ね合わせます。上部の Any から、Java のオブジェクトとプリミティブをそれぞれカバーするために AnyRef と AnyVal に膨らみ、最後に収束し、参照型を Null に、すべての型を Nothing に折りたたみます。私が理解しているように、Nothing はすべてのサブタイプです。AnyRef/java.lang.Object のすべてのサブタイプのサブタイプを null にします。[ http://www.scala-lang.org/node/128を参照]

ただし、すべての Scala 型を単純にシームレスな型階層の要素と見なすことができないいくつかの不規則性、いくつかの場所があるようです。私はこれが面倒だと思っており、私が驚くかもしれない場所を理解したいと思っています.

これまでのところ、私はいくつかの不規則性を知っています:

1) Null は AnyRef のサブタイプですが、null.isInstanceOf[AnyRef] (または AnyRef の他のサブタイプ) を呼び出すと false が返されます。これは、Java の instanceof 演算子の動作と一致するように選択されたものと思われます。

2) 分散注釈に関係なく、すべてが Nothing に対して共変です。共変とマークされていない型 T を返すメソッドがある場合、そのメソッドをオーバーライドして型 Nothing を返すことができます。[注: この主張は間違っています。以下の回答とコメントを参照してください!]

3) isInstanceOf を AnyVal 型に適用できません [ isInstanceOf チェックで AnyVal を使用できない理由を参照してください。AnyValである値をテストする方法は? ]

4) 何かが isInstanceOf[Null] かどうかを尋ねるのは違法です。これは完全に首尾一貫した質問です (ただし、「myVar == null」でも同じ答えが得られるため、特に必要ではありません)。

Scala の型階層に不規則性や特殊なケースの例は他にありますか? 歓迎されない驚きを避けるために、これらは学び、理解する価値があると思います.

4

1 に答える 1

7

1)"A string is a subtype of AnyRef".isInstanceOf[AnyRef]返品しますtrueAnyRefこれは、 を除くの他のサブタイプにも当てはまりますNull。あなたが言ったように、そこにある唯一の不規則性はJavaと一致するように行われています。

2)Bが のサブタイプA、つまりの場合B <: A、いつでもメソッドをオーバーライドできます。

def foo: A = ...

に:

override def foo: B = ...

これは戻り値の型の改良と呼ばれ、常に許可されます。Nothingは他のすべての型 ( Nothing <: Afor all ) のサブタイプであるためA、いつでも戻り値の型を調整できますNothing(たとえば、メソッドの本体で例外をスローすることによって)。これはかなり規則的なプロパティです。戻り型の共分散は、型パラメーターの分散注釈とは直接関係ありません。

3)他の質問はこれをうまくカバーしています。

4) これは、Null型が Java ランタイムに存在しないためです。これをエミュレートしたい場合は、独自のinstanceOfメソッドを作成できます。最初に引数がnullであるかどうかを確認する必要があります。それ以外の場合は、通常のisInstanceOfチェックを行います。

はい、他にも不規則性があります。例を参照してください: Int を null にできない場合、null.asInstanceOf[Int] の意味は何ですか?

instanceof配列は別の例であり、実行時にボックス化/ボックス化解除またはチェックを使用して汎用配列の均一性を支払うことができます。はnew Array[Any]オブジェクト配列に変換されます。配列に整数を格納すると、ボックス化されます。上限のないを使用する場合は常にArray[T]、要素にインデックスを付けるたびに、正しい実行時配列型に対して配列がパターン化されます。T

どのように驚かれるかをよりよく理解するには、プリミティブ型と参照型、ボックス化/ボックス化解除、およびさまざまな配列クラスの概念がある場合に、これらの構造が JVM にどのように変換されるかという観点から考えると役立ちます。

于 2012-10-10T23:19:15.180 に答える