3

私の他の質問から来て 、コンストラクターの名前によるパラメーターを機能させる方法はありますか?オブジェクト内でオンデマンド/レイジー/名前で実行されるコードブロックを提供する方法が必要です。このコードブロックは、コードブロックがクラスの一部であるかのようにクラスメソッドにアクセスできる必要があります。 。

次のテストケースは失敗します:

package test

class ByNameCons(code: => Unit) {

    def exec() = {
        println("pre-code")
        code
        println("post-code")
    }

    def meth() = println("method")

    def exec2(code2: => Unit) = {
        println("pre-code")
        code2
        println("post-code")
    }
}


object ByNameCons {

    def main(args: Array[String]): Unit = {
        val tst = new ByNameCons {
            println("foo")
            meth() // knows meth() as code is part of ByNameCons
        }
        tst.exec() // ByName fails (executed right as constructor)


        println("--------")


        tst.exec2 { // ByName works
            println("foo")
            //meth() // does not know meth() as code is NOT part of ByNameCons
        }       
    }
}

出力:

foo
method
pre-code
post-code
--------
pre-code
foo
post-code
4

3 に答える 3

6

これは、次のようなインスタンスを作成しているためです。

val tst = new ByNameCons {
  ...
}

..実際には、Javaのように匿名クラスを作成しています。上記のコードは次のものと同じです。

val tst = new ByNameCons() { ... }

..名前で渡すための正しい構文は次のとおりです。

val tst = new ByNameCons( { ... } )

関数の場合と同じように、コンストラクターの括弧を省略することはできません。

于 2011-07-26T20:33:46.230 に答える
3
val tst = new ByNameCons( {
   println("foo")  
} )

おそらくこれを行う方が簡単だと思いました:

object ByNameCons {
  def apply(code: => Unit) = new ByNameCons(code)
}

val tst = ByNameCons { // no "new" here -- can't mix traits either
  println("foo")
}
于 2010-04-15T17:15:08.597 に答える
1

理由はわかりませんが、クラスの作成時に{}または()を使用すると動作が変わるようです。次のクラスを使用して、

class Coder(code: => Unit) {
  def exec = { 
    println("before")
    code
    println("after")}
  }
}

scala> val brackets = new Coder {println("testing")}
testing
brackets: Coder = $anon$1@1af7a03
scala> brackets exec
before
after

代わりに、別の方法で定義すると、

scala> val parens = new Coder(println("testing"))
parens: Coder = Coder@dca3ed
scala> parens exec
before
testing
after

望んだ通りに。最初の表記では、コンパイラは角かっこを、Unit呼び出されたときにに評価される無名関数ではなく、に評価されるブロックとして解釈しているように見えUnitます。

FWIW、({...})の使用も正常に機能します。

于 2010-04-15T17:29:28.043 に答える