„Nowe” słowo kluczowe w Scali

96

Mam bardzo proste pytanie - kiedy powinniśmy stosować nowe słowo kluczowe podczas tworzenia obiektów w Scali? Czy dzieje się tak, gdy próbujemy utworzyć tylko instancje obiektów Java?

Bober02
źródło

Odpowiedzi:

146

Użyj newsłowa kluczowego, jeśli chcesz odwołać się do classwłasnego konstruktora:

class Foo { }

val f = new Foo

Pomiń, newjeśli odwołujesz się do metody obiektu towarzyszącego apply:

class Foo { }
object Foo {
    def apply() = new Foo
}

// Both of these are legal
val f = Foo()
val f2 = new Foo

Jeśli stworzyłeś klasę przypadku:

case class Foo()

Scala potajemnie tworzy dla Ciebie obiekt towarzyszący, zamieniając go w następujący sposób:

class Foo { }
object Foo {
    def apply() = new Foo
}

Więc możesz to zrobić

f = Foo()

Na koniec pamiętaj, że nie ma reguły, która mówi, że apply metoda towarzysząca musi być proxy dla konstruktora:

class Foo { }
object Foo {
    def apply() = 7
}

// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7

A skoro wspomniałeś o klasach Javy: tak - klasy Javy rzadko mają obiekty towarzyszące z applymetodą, więc musisz użyć newi konstruktora właściwej klasy.

piekarnik
źródło
1
Klasa Java nigdy nie może mieć obiektu towarzyszącego. Może mieć obiekt, który może działać jako fabryka dla klasy Java - ale ten obiekt nie jest jej obiektem towarzyszącym.
kiritsuku
@Antoras Skoro klasy Scala kompilują się do kodu bajtowego Javy i mogą być rozpowszechniane w formie skompilowanej, czy Scala może odróżnić rzeczywistą towarzyszkę Scali od klasy o nazwie Foo $ ze statycznym składnikiem MODULE $?
Owen
1
Myślę, że scalac może się tym różnić, ponieważ określono, że obiekt towarzyszący musi być zadeklarowany w tym samym pliku, co jego klasa towarzysząca. Ponieważ „właściwość” towarzysząca istnieje tylko w Scali, a nie na poziomie kodu bajtowego, scalac musi sprawdzić kod Scala, a nie kod bajtowy, aby mieć pewność, że przestrzegana jest specyfikacja.
kiritsuku
1
Jakieś przykłady klas Java, które NIE używają słowa kluczowego new w Scali?
Bober02
Również metody obiektu towarzyszącego zostaną udostępnione za pomocą metod statycznych w klasie, co nigdy się nie stanie w przypadku klas Java, dla których później zdefiniujesz „towarzysza”.
drexin
16

Czy dzieje się tak, gdy próbujemy utworzyć tylko instancje obiektów Java?

Ani trochę. Są dwa ogólne przypadki, w których pomijasz neww scali . Z obiektami pojedynczymi (które są często używane do przechowywania funkcji statycznych i jako rodzaj fabryki podobnej do tego, co można zobaczyć w Javie):

scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy

scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8

scala> LonelyGuy.mood
res4: java.lang.String = sad

Z klasami przypadków (właściwie pod spodem znajdują się class + object = companion pattern, np. Posiadające klasę i obiekt o tej samej nazwie):

scala> case class Foo(bar: String) 
defined class Foo


scala> Foo("baz")
res2: Foo = Foo(baz)

Więc kiedy pracujesz z prostymi klasami, reguły są takie same jak w Javie.

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

Bonus, w scali są anonimowe klasy, które można zbudować w następujący sposób:

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
mniam mniam mniam
źródło
1
Wszystko w porządku, stary?
Jacob B
0

Czy dzieje się tak, gdy próbujemy utworzyć tylko instancje obiektów Java?

Ze Scalą 3 (która powinna ukazać się w połowie 2020 roku, osiem lat później), opartą na Dotty : nigdy.

Scala 3 opuści „ new”, jak w tym wątku

Aplikacje kreatora pozwalają na użycie prostej składni wywołania funkcji do tworzenia instancji klasy, nawet jeśli nie ma zaimplementowanej metody stosującej.

Przykład:

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

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

Aplikacje twórców generalizują funkcjonalność dostarczaną dotychczas tylko dla klas przypadków, ale mechanizm, w jaki to jest osiągane, jest nieco inny.
Zamiast automatycznie generowanej metody Apply dodajemy nową możliwą interpretację do wywołania funkcji f(args).

VonC
źródło