Ключевое слово «новое» в Scala


96

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

Ответы:


146

Используйте 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и фактический конструктор класса.


1
Класс Java никогда не может иметь сопутствующего объекта. Он может иметь объект, который может работать как Factory для класса Java, но этот объект не является его сопутствующим объектом.
— kiritsuku

@Antoras Поскольку классы Scala компилируются в байт-код Java и могут распространяться в скомпилированной форме, может ли Scala отличить фактический компаньон Scala от класса с именем Foo $ со статическим членом MODULE $?
— Owen

1
Я думаю, что scalac может отличаться от этого, потому что указано, что сопутствующий объект должен быть объявлен в том же файле, что и его сопутствующий класс. Поскольку сопутствующее «свойство» существует только в Scala, а не на уровне байт-кода, скаляр должен проверять код Scala, а не байт-код, чтобы быть уверенным в соблюдении спецификации.
— kiritsuku

1
Любые примеры классов Java, которые НЕ используют ключевое слово new в Scala?
— Bober02

Кроме того, методы объекта-компаньона также будут доступны через статические методы класса, а этого никогда не произойдет с классами java, для которых вы позже определите «сопутствующего баннера».
— drexin

16

Это когда мы пытаемся создать только объекты 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

1
Ты в порядке, дружище?
— Джейкоб Би

0

Это когда мы пытаемся создать только объекты 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).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.