Ключове слово “new” у Scala


93

У мене дуже просте запитання - коли слід застосовувати нове ключове слово при створенні об’єктів у Scala? Це коли ми намагаємось створити лише екземпляри об'єктів Java?

Відповіді:


144

Використовуйте 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і конструктор власне класу.


1
Клас Java ніколи не може мати об'єкт-супутник. Він може мати об'єкт, який може працювати як Factory для класу Java, але цей об'єкт не є його супутнім об'єктом.
kiritsuku

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

1
Я думаю, що scalac може це відрізняти, оскільки зазначається, що об'єкт-супутник повинен бути оголошений у тому ж файлі, що і його клас-супутник. Оскільки супутнє "властивість" існує лише в Scala, а не на рівні байт-коду, Scalac повинен перевіряти код Scala, а не Bytecode, щоб бути впевненим у дотриманні специфікації.
кіріцуку

1
Будь-які приклади класів Java, які НЕ використовують нове ключове слово в 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
Ти добре там, дружище?
Jacob B

0

Це коли ми намагаємось створити лише екземпляри об'єктів Java?

З Scala 3 (яка має вийти в середині 2020 року, через вісім років), заснована на Dotty : never.

Scala 3 випаде " new", як у цій темі

Додатки Creator дозволяють використовувати простий синтаксис викликів функцій для створення екземплярів класу, навіть якщо немає застосованого методу apply.

Приклад:

class StringBuilder(s: String) {
   def this() = this(s)
}

StringBuilder("abc")  // same as new StringBuilder("abc")
StringBuilder()       // same as new StringBuilder()

Додатки розробників узагальнюють функціональність, що надається лише для класів кейсів, але механізм досягнення цього дещо інший.
Замість автоматично згенерованого методу застосування ми додаємо нову можливу інтерпретацію до виклику функції f(args).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.