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?
Odpowiedzi:
Użyj new
słowa kluczowego, jeśli chcesz odwołać się do class
własnego konstruktora:
class Foo { }
val f = new Foo
Pomiń, new
jeś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 apply
metodą, więc musisz użyć new
i konstruktora właściwej klasy.
Czy dzieje się tak, gdy próbujemy utworzyć tylko instancje obiektów Java?
Ani trochę. Są dwa ogólne przypadki, w których pomijasz new
w 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
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 funkcjif(args)
.