"новое" ключевое слово в 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).