2016-09-11 5 views
3

Javaでは、それらの違いははっきりしています。しかし、Scalaでは、メソッドを宣言してかっこなしで使用できます。また、私はUniform Access PrincipleがScalaが持つ哲学であることも知っています。これらはすべて、フィールドとメソッドの境界を新しい学習者にあいまいにします。メソッドとフィールドの違いは何ですか?

最初にdefvalはメソッドとフィールドの境界だと思っていました。しかし、スカラでは、valを使ってサブクラスで定義された "フィールド"がdefを使って基本クラスで定義された "メソッド"をオーバーライドできることが判明しました。

したがって、私は疑問に思う:

  1. 「場」の概念が存在しない(またはは、パラメータなしの方法と全く同じものである)かどうかScalaで?

  2. もしそうでなければ、それらの境界は何ですか?

+0

「def」と「val」がオーバーライドを超えていると言うと、other_は文が強すぎます。 'def'を' val'で上書きすることはできますが、それ以外の方法では無効にすることはできません。 –

+0

@ m-zありがとう、私は私の記述を編集しました。 –

答えて

4

これはかなり簡単です。たとえば、公開の場合val scalacは値を保持するプライベートフィールドとgetterを生成します。javapで

class A { 
    val x = 4 
} 

class A extends T { val x = 4 } 

あなたはトレイトからメソッドxをオーバーライドしているときに

trait T { def x = 1 } 

を持っていた場合、あなたはそう

public class A { 
    private final int x; 
    public int x(); 
    public A(); 
} 

を見ることができますTプライベートフィールドxへのゲッターx

1

主な違いは、

def f: Int = something 

val v = 1 

f方法をすぐに評価されません。 fは、fが明示的に呼び出されるか呼び出されるたびに評価され、vはすぐに評価されます。

通知fは宣言されても評価されませんが、宣言されるとすぐにxが評価されます。 fは、明示的に呼び出されたときに評価されます。

scala> val x = { println("evaluated"); 1} 
evaluated 
x: Int = 1 

scala> def f = { println("evaluated"); 1} 
f: Int 

scala> f 
evaluated 
res0: Int = 1 

scala> f 
evaluated 
res1: Int = 1 

継承

trait A { 
    def m: Unit 
} 

class B extends A { 
override val m: Unit = something 
} 

defvalに上書きなくその逆のことができます。 val mと宣言するとmという名前のメソッドが生成されるため、これを行うことができます。そのサブタイプのmがスーパータイプのwhatsをオーバーライドするように宣言します。

+0

はい、それは私が 'def'メソッドを定義し、' val'がフィールドを定義すると思ったことです。しかし、Scalaでは、 'def'と' val'を使って定義されたメンバは、クラス階層で実際に自由にオーバーライドすることができます。他の言語のメソッドやフィールドでは、メソッドとフィールド。 –

+0

@LifuHuang defはvalに上書きできますが、その逆はできません。一般性を失うことなく – pamu

+0

ありがとう、私は私の記述を編集しました。 –

2

あなたは、コンパイラで-printオプションをオンにしたときにそれが明確になる:

val v = List(1,2,3) 

=> 

object iw extends Object { 
    private[this] val v: List = _; 
    <stable> <accessor> def v(): List = iw.this.v; 
    def <init>(): type = { 
    iw.super.<init>(); 
    iw.this.v = 
     scala.collection.immutable.List.apply(
     scala.Predef.wrapIntArray(Array[Int]{1, 2, 3}) 
    ); 
() 
} 

}

どちらも効果的方法を定義しますが、後者の場合の初期化で対

def m = List(1,2,3) 

=> 

object iw extends Object { 
    def m(): List = 
    scala.collection.immutable.List.apply(
     scala.Predef.wrapIntArray(Array[Int]{1, 2, 3}) 
    ); 
    def <init>(): type = { 
    iw.super.<init>(); 
    () 
    } 
} 

プライベート変数は即座に発生し、単純にその値を取得しますが、前者ではそれを呼び出すたびに値を取得します。

+1

ニース!これを読んでいる人はREPLの ':settings -print'と入力することでこれを有効にすることができます。 – Steiny

関連する問題