By-Name-Parameters для конструкторов - PullRequest
2 голосов
/ 15 апреля 2010

из мой другой вопрос есть ли способ получить параметры по имени для работы конструкторов?Мне нужен способ предоставить блок кода, который выполняется по требованию / lazy / by-name внутри объекта, и этот блок кода должен иметь возможность доступа к методам класса, как если бы блок кода был частью класса.

Сбой следующего теста:

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

Ответы [ 3 ]

5 голосов
/ 27 июля 2011

Это потому, что когда вы создаете такой экземпляр:

val tst = new ByNameCons {
  ...
}

.. вы на самом деле создаете анонимный класс, как в Java. Код выше такой же, как:

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

.. в то время как правильный синтаксис для передачи имени:

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

Вы не можете опустить круглые скобки для конструкторов так же, как и для функций.

3 голосов
/ 15 апреля 2010
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")
}
1 голос
/ 15 апреля 2010

Я не знаю почему, но похоже, что использование {} или () при создании класса меняет поведение. Используя следующий класс,

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, использование ({...}) также отлично работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...