2011-12-15 11 views
5

W Rozdziale 22 „Programowanie w Scala” książce, że :: klasy (cons) jest zdefiniowana jakoKorzystanie nowy z Scala końcowej klasie przypadku

final case class ::[T](hd: T, tl: List[T]) extends List[T] { 
    //... 
} 

Sposób :: w klasie List jest zdefiniowany następująco:

def ::[U >: T](x: U): List[U] = new scala.::(x, this) 

Dlaczego new wymagane do utworzenia instancji finalcaseclass ::? Czy to wyłącznie w celu ujednoznacznienia?

+4

Finał oznacza, że ​​klasa nie może być rozszerzona, nie ma nic wspólnego z tworzeniem instancji :-). Klasa case to w zasadzie klasa, którą można porównać w bloku "match case". – aishwarya

Odpowiedz

6

z klasami przypadków automatycznie uzyskać obiekt towarzysz, którego apply metoda wywołuje konstruktor, w taki sam sposób, jak można to zrobić za pomocą zwykłego klasy:

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) } 

val x = new Foo(42) // 
val y = Foo(42)  // both work the same 

Można instancję klasy etui z new jeśli ciebie chcieć. Teoretycznie może być nieco szybszy, ponieważ nie musi przejść przez metodę obiektu towarzyszącego apply, ale próbowałem szybkiego testu porównawczego i nie widziałem absolutnie żadnej różnicy w wydajności, więc myślę, że jest zoptymalizowany przez kompilator, lub po prostu niezmiernie mały różnica w stosunku do faktycznej konstrukcji.

Więc nie sądzę, że new w podanym przykładzie ma jakiekolwiek znaczenie i równie dobrze mogłoby zostać pominięte.

3

Masz rację; new nie jest obowiązkowe. Mogli zdefiniowano metodę instancji List#:: jak to równie dobrze:

def ::[U >: T](x: U): List[U] = scala.::(x, this) 

(Zauważ, że mamy:

type :: = collection.immutable.:: 
val :: = collection.immutable.:: 

zdefiniowane w obiekcie scala pakietu; pierwsza to dlaczego twoje prace new scala.::(x, this) i po drugie dlatego mój scala.::(x, this) działa.)

The form the library uses dzwoni do konstruktora bezpośrednio, tak jak twój. Alternatywa wywołuje metodę apply syntetycznego obiektu towarzyszącego wygenerowanego dla klasy przypadku ::, która po prostu wywołuje konstruktor mimo to. Być może dzwonienie do konstruktora było uważane za wyraźniejsze lub bardziej wydajne? (. Przyrost wydajności powinna być zbliżona do zera, chociaż, ponieważ jeśli kompilator nie inline wywołanie apply, JVM będzie) Przypuszczam, że najbardziej kompaktową formę:

def ::[U >: T](x: U) = ::(x, this) 

mógłby być wzięty za jakiś głupi (tj. niemożliwy) rodzaj rekursywnej inwokacji, a w każdym razie zaciera rozróżnienie między klasą o nazwie :: a metodą ::, którą Prof. Odersky dokłada starań, aby zachować odrębność w celu zmaksymalizowania zrozumienia czytnika.

Mam nadzieję, że to pomoże.

Powiązane problemy