Как работают фигурные фигурные скобки после создания экземпляра?

Я нахожу какое-то запутанное использование признака в каком-то кодексе unittesting, например:

trait MyTrait {
  val t1 = ... //some expression
  val t2 = ... //some expression
}

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

test("it is a test") {
  new MyTrait {
    // do something with t1 and t2
  }
}

Я смущен этим странным синтаксисом.

Мой вопрос:

  • зачем использовать последующее создание признаков с помощью фигурных скобок?

  • Какова цель создания экземпляра в этом случае, и другие случаи также могут быть полезны?

Ответ 1

Вы не создаете черты: черты сами по себе не могут быть созданы; могут быть только не абстрактные классы. То, что вы здесь делаете, использует сокращение Scala для определения анонимного/безымянного класса, который расширяет черту и создает экземпляр в том же самом выражении.

val anonClassMixingInTrait = new MyTrait {
  def aFunctionInMyClass = "I'm a func in an anonymous class"
}

Является эквивалентом:

class MyClass extends MyTrait {
  def aFunctionInMyClass = "I'm a func in a named class"
}

val namedClassMixingInTrait = new MyClass

Разница заключается в том, что вы можете установить этот анонимный класс только во время определения, так как он не имеет имени и не может иметь аргументов конструктора.

Ответ 2

Стив Баззард уже объяснил, какие анонимные классы, но вы также просили об этом. Цель здесь заключается в том, что в тестах вы часто используете некоторые значения по умолчанию, которые вы хотите использовать в каждом тесте. Иногда у вас также есть состояние, которое может быть изменено некоторыми тестами. Чтобы всегда начинать с правильных значений (тесты также могут выполняться параллельно), вы можете инкапсулировать их в этих анонимных экземплярах. Код внутри этого анонимного экземпляра - это конструктор, который будет оцениваться при создании экземпляра, тем самым выполняя ваши тесты.

Ответ 3

val t = new MyTrait {
  val t1 = ... //some expression
  val t2 = ... //some expression
}

совпадает с

val t = new AnyRef with MyTrait {
  val t1 = ... //some expression
  val t2 = ... //some expression
}

совпадает с

val t = new Object with MyTrait {
  val t1 = ... //some expression
  val t2 = ... //some expression
}