2010-04-18 5 views
18

Zastanawiasz się, czy to jest możliwe. Co chciałbym zrobić, to sprawdzić i ewentualnie zmodyfikować jeden z argumentów, zanim zostanie zapisany jako wartość.Scala: czy można zastąpić domyślny konstruktor klasy case?

Alternatywnie można użyć przeciążenia i ustawić domyślny konstruktor jako prywatny. W takim przypadku chciałbym również uczynić prywatny domyślny konstruktor fabryczny w obiekcie towarzyszącym, w jaki sposób mógłbym to zrobić?

Wielkie dzięki.

Adam

edit: dobrze zorientowali się, że zarabianie prywatny konstruktor domyślny sprawia również domyãlnego konstruktora prywatny, więc mam rozwiązanie, nadal jestem zainteresowany, aby wiedzieć, czy konstruktor domyślny jest przeciążać chociaż

+3

Dlaczego chcesz to zrobić? Klasa case ma być używana do definiowania algebraicznych typów danych, więc dodany konstruktor, który zmienia argumenty wywołującego, jest kłamstwem. Jeśli chodzi o sprawdzanie poprawności argumentów, można to zrobić w głównym konstruktorze za pomocą 'assert' lub' require'. –

+0

@ adam77 Aby zmienić początkowe zdanie jako pytanie "Czy mogę sprawdzić i ewentualnie zmodyfikować [parametr klasy sprawy]?" Odpowiedź brzmi tak. Właśnie wysłałem szczegóły dotyczące pokrewnego pytania znajdującego się tutaj: http://stackoverflow.com/a/25538287/501113 – chaotic3quilibrium

Odpowiedz

11

Obecność konstruktorów klas drugorzędnych nie powoduje, że kompilator tworzy dodatkowe metody fabryczne w towarzyszach klasy, więc nie będzie można uzyskać wygody tworzenia ich za pomocą CaseClaseName(«secondary constructor parameter list»>). Będziesz musiał użyć słowa kluczowego new.

Lepiej jest umieścić rodzaj logiki, którą opisujesz w alternatywnych metodach fabrycznych w obiekcie towarzyszącym i trzymać się przy użyciu głównego konstruktora.

3

Możesz przeciążać konstruktory. Jest taki sam jak w C++ lub Java. Po prostu zrób kolejny konstruktor.

class Foo(_input:Int){ 
    def this() = this(0) 
} 

Lub można zobaczyć post this SO.

+1

Dzięki, ale pytanie jest przesłonięcie, nie przeciążenie. – adam77

+8

Nie można zastąpić żadnego konstruktora, ponieważ nie są one dziedziczone na początek. –

1

Możesz przekształcić zwykłą klasę w klasę pseudo-case, pisząc własne metody apply (dla fabryki) i unapply (dla dopasowania wzorca) w obiekcie towarzyszącym. Lub możesz po prostu napisać nazwaną metodę fabryki w obiekcie towarzyszącym klasy sprawy.

22

Nie masz możliwości zmiany sposobu, w jaki domyślny konstruktor przechowuje jego parametry (np. Modyfikując parametry, zanim zostaną zapisane jako val s), ale masz opcję wyrzucenia wyjątku, jeśli parametry są błędne (to nastąpi po parametry są przechowywane)

case class Foo(x:Int){ 
    if (x<0) throw SomeException; 
} 

masz również możliwość realizacji dodatkowych konstruktorów, które wywołują pierwszego konstruktora

case class Foo(x:Int){ 
    def this(x:Int,y:Int) = this(x+y) 
} 

ale nie rozumiem tych metod fabrycznych.

Można łatwo tworzyć metody fabryki dopisując go do obiektu towarzyszącego

object Foo{ 
    def apply(x:Int,y:Int) = new Foo(x,y) 
} 

coś jeszcze bardziej skomplikowane i trzeba zrezygnować klasę case i realizować to części na własną rękę: apply , unapply, equals i hashCode. Programowanie w Scali mówi o tym, jak to zrobić, dając dobre formuły dla equals i hashCode.

+0

Istnieje możliwość bezpiecznej zmiany parametrów przed ich zapisaniem w klasie case. I nadal możesz zrobić kilka bardziej skomplikowanych rzeczy bez rezygnowania z zalet klas przypadków. Właśnie przedstawiłem moje rozwiązanie w innym wątku: http://stackoverflow.com/a/25538287/501113 – chaotic3quilibrium