"новое" ключевое слово в Scala

У меня очень простой вопрос - когда мы должны применять новое ключевое слово при создании объектов в Scala? Это когда мы пытаемся создавать экземпляры только Java-объектов?

2 ответа

Решение

Использовать 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 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 в скале. С одноэлементными объектами (которые часто используются для хранения статических функций и как своего рода фабрика, похожая на ту, что вы видели в 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

В случае классов (на самом деле под ними есть шаблон + класс = сопутствующий шаблон, например, имеющий класс и объект с одинаковым именем):

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).

Другие вопросы по тегам