短い答え:
私の知る限り、値は常にアクセサーメソッドを介してアクセスされます。Usingdef
は、値を返す単純なメソッドを定義します。Usingは、アクセサメソッドを使用してプライベート[*]最終フィールドをval
定義します。したがって、アクセスに関しては、2つの間にほとんど違いはありません。違いは概念的なものであり、毎回再評価され、一度だけ評価されます。これは明らかにパフォーマンスに影響を与える可能性があります。def
val
[*]Javaプライベート
長い答え:
次の例を見てみましょう。
trait ResourceDef {
def id: String = "5"
}
trait ResourceVal {
val id: String = "5"
}
ResourceDef
&はResourceVal
、初期化子を無視して、同じコードを生成します。
public interface ResourceVal extends ScalaObject {
volatile void foo$ResourceVal$_setter_$id_$eq(String s);
String id();
}
public interface ResourceDef extends ScalaObject {
String id();
}
生成された補助クラス(メソッドの実装を含む)の場合、ResourceDef
生成は予想どおりであり、メソッドは静的であることに注意してください。
public abstract class ResourceDef$class {
public static String id(ResourceDef $this) {
return "5";
}
public static void $init$(ResourceDef resourcedef) {}
}
valの場合、包含クラスのイニシャライザーを呼び出すだけです。
public abstract class ResourceVal$class {
public static void $init$(ResourceVal $this) {
$this.foo$ResourceVal$_setter_$id_$eq("5");
}
}
拡張を開始するとき:
class ResourceDefClass extends ResourceDef {
override def id: String = "6"
}
class ResourceValClass extends ResourceVal {
override val id: String = "6"
def foobar() = id
}
class ResourceNoneClass extends ResourceDef
オーバーライドすると、期待どおりのことを実行するメソッドがクラスに取得されます。defは単純な方法です:
public class ResourceDefClass implements ResourceDef, ScalaObject {
public String id() {
return "6";
}
}
valは、プライベートフィールドとアクセサメソッドを定義します。
public class ResourceValClass implements ResourceVal, ScalaObject {
public String id() {
return id;
}
private final String id = "6";
public String foobar() {
return id();
}
}
foobar()
フィールドを使用せずid
、アクセサメソッドを使用することに注意してください。
そして最後に、オーバーライドしない場合、トレイト補助クラスの静的メソッドを呼び出すメソッドを取得します。
public class ResourceNoneClass implements ResourceDef, ScalaObject {
public volatile String id() {
return ResourceDef$class.id(this);
}
}
これらの例ではコンストラクターを切り取っています。
したがって、アクセサメソッドが常に使用されます。これは、同じメソッドを実装できる複数のトレイトを拡張する際の複雑さを回避するためだと思います。それは本当にすぐに複雑になります。
さらに長い答え:
Josh Suerethは、Scala Days2012でBinaryResilienceについて非常に興味深い講演を行いました。これは、この質問の背景をカバーしています。このための要約は次のとおりです。
この講演では、JVMでのバイナリ互換性と、バイナリ互換であるとはどういう意味かについて説明します。Scalaでのバイナリ非互換性の策略の概要が
詳細に説明され、その後、開発者が独自のライブラリリリースがバイナリ互換でバイナリ耐性があることを確認するのに役立つ一連のルールとガイドラインが続きます。
特に、この講演では以下を取り上げます。
- 特性とバイナリ互換性
- Javaシリアル化と匿名クラス
- 怠惰なvalsの隠された創造物
- バイナリ耐性のあるコードの開発