Я очень новичок в области Scala, в последнее время пытаюсь поиграть с платформой Play. Я использовал консоль Play для создания своего первого приложения.

После этого я читаю код, но для следующих фрагментов кода я просто запутался.

package controllers

import play.api._
import play.api.mvc._

object Application extends Controller {

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

С точки зрения документации Action - это сопутствующий объект, но каков синтаксис сопутствующего объекта, следующего за фигурными скобками, похож ли он на анонимную реализацию интерфейса в Java, или содержимое внутри фигурных скобок является переопределением метода apply?

Пожалуйста, посоветуйте, большое спасибо. Простите за наивный и простой вопрос ветеранам Scala.

1
Bo Ye 27 Дек 2014 в 08:31

2 ответа

Лучший ответ

Это синтаксический сахар для Action.apply. (У вас не может быть анонимной реализации object, но вы могли бы, если бы это был trait, это также потребовало бы new). У него есть несколько перегрузок:

final def apply[A](bodyParser: BodyParser[A])(block: R[A] => Result): Action[A]

final def apply(block: R[AnyContent] => Result): Action[AnyContent]

final def apply(block: => Result): Action[AnyContent]

Ваш фрагмент использует последний из этих трех. Между прочим, все они возвращают объекты, реализующие трейт Action[A].

1
Michael Zajac 27 Дек 2014 в 15:12

Действие - это черта, расширяющая EssentialAction

trait Action[A] extends EssentialAction

Essential Action - это не что иное, как функция. При наличии RequestHeader EssentialAction использует тело запроса (массив [байт]) и возвращает результат.

trait EssentialAction extends (RequestHeader) ⇒ Iteratee[Array[Byte], Result] with Handler

ActionBuilder - это вспомогательная черта, у которой есть методы для создания Action. Именно эта черта содержит несколько перегруженных методов async и apply. Если вы хотите определить настраиваемое действие (или) объединить одно действие в другое (или) выполнить одно действие за другим, вы должны использовать эту черту и создать свое собственное действие.

trait ActionBuilder[+R[_]] extends ActionFunction[Request, R]

Но каков синтаксис Action {...}. У свойства ActionBuilder есть объект-компаньон , который также имеет то же имя Action. Обратите внимание, что это отличается от Действие поезда [A]. Этот объект переопределяет метод InvokeBlock. В scala вы также можете определять объекты. Вы определяете объект и предоставляете метод apply, который вызывается при вызове объекта.

object Action extends ActionBuilder[Request] {companion
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = block(request)
}

То, что вы передаете в фигурных скобках {...}, - это не что иное, как блок, определенный как параметр в invokeBlock. В scala вы можете передавать аргументы функции, используя скобки или фигурные скобки, фигурные скобки хорошо работают, когда у вас есть многострочное выражение, такое как блок. Этот метод invokeBlock вызывается из перегруженной версии apply в трейте ActionBuilder.

Я понимаю, это немного ошеломляет, чтобы понять, что происходит внутри скобок, чувствую себя легко, мне потребовалось около 10 дней, чтобы понять это. Добро пожаловать в Scala !!!

Источник:

  1. исходный код - https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/api/mvc/Action.scala

  2. скудная документация - https://www.playframework.com/documentation/2.3.x/ScalaActionsComposition < / а>

  3. воспроизвести документы api - https: / /www.playframework.com/documentation/2.3.x/api/scala/index.html#play.api.mvc.ActionBuilder

  4. Отличный блог о композиции действий - http://www.mariussoutier.com/blog/2013/09/17/playframework-2-2-action-building-action-composition/

2
vumaasha 28 Дек 2014 в 03:52