Scala方法 = 特质{ ... }的含义

4

我正尝试同时学习Scala和Play框架。Scala看起来有很多非常酷的想法,但是我的一个挫折是试图理解方法/函数/lambda/匿名函数等不同语法。

所以我的主要应用程序控制器如下:

object Application extends Controller {
  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }
}

这告诉我我有一个单例Application,它有一个方法index,返回什么类型?我原本期望index的定义更像是:
def index(req: Request) : Result = { ... }

看Play Framework的文档,似乎Action是一个特质(trait),它将请求转换为结果,但我很难理解这行代码的意思:

def index = Action { ... }

我来自Java背景,所以不知道这是什么意思?(这个语句感觉像是在说"方法索引 = [某些接口行为]",这对我来说毫无意义;似乎有一些美妙的事情正在发生,但它对我来说就像是魔法一样,让我感到不安)


我再试着理解一下这个问题:def index = Action { ... } 是不是相当于说 index = new Action { _接口实现_ }(例如在Java中的匿名接口实例化)? - Jonathan Apodaca
我理解你在语法上感到不知所措的感觉。当其他方法都无效时,有几个工具可以使用:使用调试器进行步进调试,以及使用编译器的-Xprint:all选项。 - Ed Staub
2个回答

3
当您像调用函数一样调用对象时,这将被翻译为调用apply。即:
foo(bar)

被翻译成

foo.apply(bar)

所以,在index内部,您调用Action对象就像调用函数一样,这意味着您实际上正在调用Action.applyindex的返回类型被省略,因为编译器可以推断它是Action.apply的返回类型(从名称推测,应该是Unit)。

很好,感谢您花时间解释。这开始变得有意义了。看着这个页面:http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.mvc.Action 看起来 Action.apply 返回 Future[SimpleResult]?但是如果我把它放在我的 index 定义中,它就无法编译(但正如您建议的那样,Unit 可以)。这里发生了什么?另外,Action 还定义了 abstract parser: BodyParser[A],为什么我根本不需要定义这个方法? - Jonathan Apodaca
1
我猜他是在一个匿名 Action 伴生对象的子类上调用 apply,并为其提供了一个初始化器(Ok(...))。如果是这样的话,那对于我们 Java 开发者来说就容易理解多了。 - Ed Staub
1
花括号是参数的另一种语法形式。您可以使用圆括号或花括号传递参数。通常,将旨在作为代码块的参数传递到花括号中,以使它们看起来像代码块。 - Jörg W Mittag
1
@JörgWMittag 大括号不是圆括号的替代品。大括号只是包装一段代码并组成一个表达式,然后可以将其作为参数传递。 - ghik
1
有趣。那么让我逐步了解一下,确保我理解得正确:def index = Action { ... } 表示“index是通过调用Action.apply({...})返回的函数”。也就是说,代码块 {...} 被传递给了 Action.apply - Jonathan Apodaca
显示剩余5条评论

1
那么,这个问题的简短答案是有些东西在幕后发生,使得上面的代码工作起来:编译器在推断类型,并且在Scala中,具有apply方法的对象可以像函数一样被调用。 因此,这里所发生的情况是:这段代码:
def index = Action {
  Ok("Hello World!")
}

...等同于(或者更确切地说是简写)以下代码:

def index : Action[AnyContent] = Action.apply(
    (req: Request[AnyContent]) => {
        Ok(views.html.index("Hello World!"))
    } : Result
)

这里的魔法就在这里发生:... = Action {...}Action {...} 表示“使用此匿名函数 {...} 调用 Action”。
由于 Action.apply 的定义为 apply(block: => Result): Action[AnyContent],因此可以推断出所有参数和返回类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接