У мене дуже просте запитання - коли слід застосовувати нове ключове слово при створенні об’єктів у Scala? Це коли ми намагаємось створити лише екземпляри об'єктів Java?
Відповіді:
Використовуйте 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
в 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
Це коли ми намагаємось створити лише екземпляри об'єктів 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)
.