2012-01-10 17 views
6

Co się stanie, gdy superklasa ma finał zaznaczony w polu, ale podklasa nadpisuje (ukrywa?) To pole? "Finał" nie kończy tego, prawda? Konkretny przykład, nad którym pracuję, to klasa budynków, z której dziedziczą różne rodzaje budynków. Koszt każdego rodzaju powinien być, między innymi, ostateczny dla każdej podklasy, ale każdy rodzaj budynku powinien mieć własny koszt.Dziedziczenie ostatnich pól w Javie?

Edytuj: Od tego czasu zdałem sobie sprawę, że nie miałem pojęcia o czym mówiłem powyżej. To, czego naprawdę chcę, to statyczne zmienne kosztów. Jednakże, jeśli zadeklaruję te zmienne statyczne w nadklasie, są one statyczne dla nadklasy, więc Subclass1.cost, np., Odnosi się do tej samej wartości, co Superclass.cost lub Subclass2.cost. Jak utworzyć zmienne, które są statyczne dla każdej podklasy, bez konieczności zadeklarowania ich w każdej klasie.

+0

Wykorzystaj pole prywatne. –

+0

Coś jak zmiany kosztów od czasu do czasu w prawo? Po co go finalizować. Nie wydaje mi się, żeby ukrywanie pola było dobrym pomysłem. –

Odpowiedz

11

final słów kluczowych, gdy stosowane do pól klasy Java, nie ma nic wspólnego z dziedziczenia. Zamiast tego wskazuje, że poza konstruktorem tego pola nie można ponownie przypisać.

Java traktuje ukrywanie i nadpisywanie osobno. Nadpisywanie w rzeczywistości powoduje zmianę obserwowalnego zachowania programu w czasie wykonywania poprzez przełączenie, która funkcja jest wywoływana, podczas gdy ukrywanie nazwy zmienia program poprzez zmianę statycznej interpretacji, które pole jest odniesieniem. final jako stosowane do nadpisywania działa tylko w przypadku metod, ponieważ pola w Javie nie mogą być nadpisane. Używanie final w tych różnych kontekstach jest niestety dość mylące i nie ma sposobu, aby zapobiec ukrywaniu nazwy pola w podklasie.

Jeśli chcesz, aby budynki miały różne koszty, jedną z opcji byłoby zastąpienie metody getCost, która jest nadpisana inaczej w każdej klasie pochodnej. Alternatywnie, możesz mieć pojedyncze pole protected lub private w klasie bazowej, które przechowuje koszt, następnie każda podklasa ustawi to pole bezpośrednio (jeśli jest to protected) lub przez konstruktor klasy podstawowej (jeśli to pole to private).

Mam nadzieję, że to pomoże!

+0

Mówisz więc, aby uczynić chronione pole w superklasie, która jest automatycznie przypisywana innym wartościom w konstruktorze podklasy? Brzmi rozsądnie. – TheTedinator

+1

@TheTedinator - To zadziała, jeśli zrezygnujesz z modyfikatora "końcowego" dla pola. Jeśli pole jest "ostateczne", nie można mu przypisać innych wartości w konstruktorze podklasy. Zamiast tego konstruktor podklasy musiałby przekazać wartość do konstruktora nadklasy, który ma zostać przypisany (jak pokazałem w mojej odpowiedzi). Jeśli nadklasa nie przypisuje wartości do swojego konstruktora, kod nie zostanie skompilowany; jeśli konstruktor podklasy próbuje ustawić wartość pola 'final' z nadklasy, kod nie zostanie skompilowany. –

+0

@templatetypedef "wskazuje, że poza konstruktorem to pole nie może być ponownie przypisane" nie jest poprawne: Ostateczne pole nie może być w ogóle przypisane, nawet w konstruktorze. Z tego powodu konstruktor podklasy nie może przesłonić ostatniego pola nadklasy, jak stwierdził Ted Hopp. – Sebastian

3

Możesz to zrobić na dwa sposoby: stwórz funkcję dostępową i ukryj to pole, albo przekaż koszt budynku konstruktorowi nadklasy z podklasy. Można łączyć je i sprawiają, że nieruchomość nie może być przesłonięta przez podklasy:

public class Building { 
    private final int cost; 

    protected Building(int cost, ...) { 
     this.cost = cost; 
    } 

    public final int getCost() { 
     return cost; 
    } 
} 

public class Cottage extends Building { 
    public Cottage() { 
     super(COTTAGE_COST, ...); 
    } 
} 
1

Zgadzam się z innych odpowiedzi, ale myślę, że po implementacji jest lepiej w tym przypadku:

public abstract class Building { 

     private final int cost; 

     public Building(int cost) { 
      this.cost = cost; 
     } 

     public final int getCost() { 
      return cost; 
     } 
    } 

    class Skyscraper extends Building { 
     public Skyscraper() { 
      super(100500); 
     } 
    } 

Oczywiście pole może zostać podane do wiadomości publicznej, ale to inna historia ...