2012-05-03 30 views
11

Dość proste ćwiczenia z książki Cay Horstmann za «Scala dla niecierpliwych» trzyma mnie zastanawiające. To około primary, auxiliary i default primary konstruktorzy:konstruktory w Scala (podstawowy/pomocniczy/default podstawowe)

ex 5.10: rozważyć klasa

class Employee(val name: String, var salary: Double) { 
    def this() { this("John Q. Public", 0.0) } 
} 

przepisać używać jawnych pól i konstruktora domyślnego podstawową.

Nie jestem pewien, czy powinienem to zrobić. Czy niektórzy z was mogą zaproponować rozwiązanie?

Jednak próby rozwiązania tego zadania mogły uświadomiły mi czegoś nie zauważyłem wcześniej o podstawowym konstruktora i val dziedzinach (jak widać, nie jestem pewny):

Am I tak, jeśli powiem, że pole val (jako name w powyższej klasie) może być inicjowane tylko przez konstruktor primary, a nie przez jeden auxiliary? W tym drugim przypadku kompilator uznałby to za zmianę przypisania do pola val powodującego błąd.

Najpierw myślałem o polach val jako przybliżonym odpowiedniku ostatecznych pól w java, spodziewając się, że byłoby legalne przypisanie ich po raz pierwszy w każdym konstruktorze, ale wydaje mi się, że się myliłem.

Nie jestem całkiem zadowolony z tego, co może być tylko dzikie domysły, więc byłbym wdzięczny, gdyby ktoś mógł dać mi dokładniejsze informacje na temat tego punktu.

+0

Miałem to dokładne pytanie z tego samego ćwiczenia. Może jestem zdezorientowany tym, co autor rozumie przez "wyraźny". – vmayer

Odpowiedz

12

Od „Programowanie w Scala, 2nd edition” pkt 6.7:

w Scala, każdy konstruktor pomocniczy musi powołać innego konstruktora tej samej klasy co jego pierwszej akcji. Efektem netto tej reguły jest to, że każde wywołanie konstruktora w Scali zakończy się ostatecznie wywołaniem podstawowego konstruktora klasy. Podstawowy konstruktor jest zatem pojedynczym punktem wejścia klasy.

Tak więc wszystkie dane do zainicjowania val muszą znajdować się w podstawowym konstruktorze.

Twoja klasa z wyraźnymi pól może być coś takiego:

class Employee(n: String = "John Q. Public", s: Double = 0.0) { 
    val name = n 
    var salary = s 
} 

lub bez wartości parametrów domyślnych:

class Employee(n: String, s: Double) { 
    def this() = this("John Q. Public", 0.0) 
    val name = n 
    var salary = s 
} 
+0

Dziękuję za odpowiedź. Podszedłem do rozwiązania dość blisko twojego, ale pomyślałem, że nie jest ono zgodne z celem ćwiczenia, ponieważ uznałem, że "domyślny konstruktor podstawowy" był "nie jawnie deklarowanym nudnym konstruktorem bez parametru". –

11

Właściwie, co miałem na myśli to wersja z podstawowym bez argumentów konstruktor, tak:

class Employee { 
    private var _name = "John Q. Public" 
    var salary = 0.0 
    def this(n: String, s: Double) { this(); _name = n; salary = s; } 
    def name = _name  
} 

Oczywiście, jest to gorsze od definiowania pól w T on pierwotny konstruktor, o co chciałem.

+1

Wielkie dzięki za poświęcenie czasu na wyjaśnienie celu ćwiczenia. Głęboko dziękuję Ci za książkę, która jest dość komplementarna z dziełami Martina Odersky'ego i sprawia, że ​​bardziej niż jakakolwiek inna książka na ten temat, pierwsze kroki w Scali są prostsze i przyjemniejsze. –