"новое" ключевое слово в Scala
У меня очень простой вопрос - когда мы должны применять новое ключевое слово при создании объектов в Scala? Это когда мы пытаемся создать экземпляр объектов Java?
Ответы
Ответ 1
Используйте ключевое слово new
, если вы хотите обратиться к собственному конструктору class
:
class Foo { }
val f = new Foo
Omit 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)
[email protected]
> println(Foo())
7
И, поскольку вы упомянули классы Java: да - классы Java редко имеют
сопутствующие объекты с помощью метода apply
, поэтому вы должны использовать new
и
класса.
Ответ 2
Это когда мы пытаемся создать экземпляр java-объектов?
Совсем нет. Существует два общих случая, когда вы опускаете new
в scala.
С объектами singleton (которые часто используются для хранения статических функций и как вид factory, аналогичный тому, что вы можете видеть в java):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = [email protected]
scala> LonelyGuy.mood
res4: java.lang.String = sad
С case-классами (на самом деле под шаблоном класса + 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 = [email protected]
// 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} = [email protected]
scala> res2.bar
res3: java.lang.String = baz
Ответ 3
Это когда мы пытаемся создавать экземпляры только Java-объектов?
С Scala 3 (который должен быть выпущен в середине 2020 года, восемь лет спустя), на основе Dotty: никогда.
Scala 3 будет сбрасывать " new
", как в этой теме
Приложения-создатели позволяют использовать простой синтаксис вызова функции для создания экземпляров класса, даже если не реализован метод применения.
Пример:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Приложения-создатели обобщают функциональность, предоставленную на данный момент, только для классов дел, но механизм достижения этого немного отличается.
Вместо автоматически сгенерированного метода apply мы добавляем новую возможную интерпретацию к вызову функции f(args)
.