«новое» ключевое слово в Scala - PullRequest
87 голосов
/ 16 марта 2012

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

Ответы [ 3 ]

132 голосов
/ 16 марта 2012

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

15 голосов
/ 16 марта 2012

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

с классами внизу есть шаблон 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
0 голосов
/ 12 июня 2019

Это когда мы пытаемся создавать экземпляры только Java-объектов?

С Scala 3 (который должен быть выпущен в середине 2020 года, восемь лет спустя), на основе Дотти : никогда.

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

...