У меня очень простой вопрос - когда мы должны применять ключевое слово new при создании объектов в Scala? Это когда мы пытаемся создать только объекты Java?
Ответы:
Используйте new
ключевое слово, если хотите обратиться к class
собственному конструктору:
class Foo { }
val f = new Foo
Пропустите, new
если вы имеете в виду метод сопутствующего объекта apply
:
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
Если вы создали класс case:
case class Foo()
Scala тайно создает для вас объект-компаньон, превращая его в этот:
class Foo { }
object Foo {
def apply() = new Foo
}
Так ты можешь сделать
f = Foo()
Наконец, имейте в виду, что не существует правила, согласно которому сопутствующий apply
метод должен быть прокси для конструктора:
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7
И, поскольку вы упомянули классы Java: да - классы Java редко имеют сопутствующие объекты с apply
методом, поэтому вы должны использовать new
и фактический конструктор класса.
Это когда мы пытаемся создать только объекты java?
Не за что. Есть два общих случая, когда вы пропускаете new
в scala. С одноэлементными объектами (которые часто используются для хранения статических функций и как своего рода фабрика, похожая на то, что вы можете видеть в java):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8
scala> LonelyGuy.mood
res4: java.lang.String = sad
С классами case (на самом деле, внизу есть шаблон class + object = companion , например, имеющий класс и объект с тем же именем):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
Поэтому, когда вы работаете с простыми классами, правила такие же, как и в Java.
scala> class Foo(val bar: String)
defined class Foo
scala> new Foo("baz")
res0: Foo = Foo@2ad6a0
// will be a error
scala> Foo("baz")
<console>:8: error: not found: value Foo
Foo("baz")
Бонус, в scala есть анонимные классы, которые можно сконструировать так:
scala> new { val bar = "baz" }
res2: java.lang.Object{val bar: java.lang.String} = $anon$1@10ee5b8
scala> res2.bar
res3: java.lang.String = baz
Это когда мы пытаемся создать только объекты Java?
Со Scala 3 (который должен быть выпущен в середине 2020 года, восемь лет спустя) на основе Dotty : никогда.
Scala 3 упадет " new
", как в этой теме
Приложения-создатели позволяют использовать простой синтаксис вызова функций для создания экземпляров класса, даже если не реализован метод apply.
Пример:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Приложения-создатели обобщают функциональность, предоставленную до сих пор только для классов case, но механизм, как это достигается, немного отличается.
Вместо автоматически сгенерированного метода apply мы добавляем новую возможную интерпретацию к вызову функцииf(args)
.