4

理解できない。Scalaがフィールドとしてオーバーライドメソッドをサポートするのはなぜですか?

abstract class A {
    def i: Int;
}

class B extends A {
    val i = 123;
}

val obj:A = new B();

println(obj.i)

メソッドiはフィールドとしてiです。なんで?

4

2 に答える 2

9

ここで何が起こっているかを確認する簡単な方法の1つは、このコードをコンパイルjavapし、結果のクラスを検査するために使用することです。ここでは、次のようになりますA

public abstract class A implements scala.ScalaObject {
  public abstract int i();
  public A();
}

そしてB(と-p、だから私たちはプライベートメンバーを見る):

public class B extends A implements scala.ScalaObject {
  private final int i;
  public int i();
  public B();
}

したがって、命名規則は異なりますが(コンパイラが処理するため、実際には規則valではありません)、慣用的なJavaで記述したものとよく似たゲッター付きのプライベートフィールドになります。

于 2012-12-17T11:06:44.930 に答える
4

Travisの回答は、実装レベルで、一部のメソッドをScalaのフィールドでオーバーライドする方法を説明していますが、その理由は説明していませなぜ質問への答えは、2つのプログラミング言語設計原則に関連しています:統一アクセス原則リスコフ置換原則

統一アクセスの原則は、基本的に、呼び出し元がメソッドを介してプロパティを読み取ることとフィールドを介してプロパティを読み取ることを区別する必要がないことを示しています。どちらの呼び出しも同じように見え、ストレージと計算のどちらを含むかを裏切らないようにする必要があります。

リスコフの置換原則は、基本的に、サブタイプはその親タイプのすべての契約を尊重しなければならないと述べています。サブタイプ、その親タイプよりも強力なコントラクトを尊重できますが、その親のコントラクトに違反してはなりません。

Scalaではdef、パラメーターリストなしでaを宣言することは、特定のコントラクトを意味します。つまり、関連付けられたプロパティにアクセスすると、宣言された型の値が返されることを意味します。参照透過性保証されていないため、以降のアクセスでは同じ値が返される場合と返されない場合があります。

明らかに、avalは同じ契約を満たしています。ただし、avalはさらに強力な保証を行います。すべてのアクセスが同じ値になります。これはより強力なvalコントラクトであるため、サブタイプがを実装するために使用するリスコフの置換原則と完全に一致していdefます。同じように、サブタイプがを使用してdefを実装することは禁止されていvalます。

于 2012-12-18T02:32:24.550 に答える