class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
Funkcja doIt wypisze „tato”. Czy jest sposób, aby wydrukować „syn”?
java
inheritance
overriding
Dikla
źródło
źródło
Odpowiedzi:
Tak. Ale jeśli chodzi o zmienną, jest ona nadpisywana (Nadanie zmiennej zmiennej nowej wartości. Nadanie nowej definicji funkcji to Zastąp).
Just don't declare the variable but initialize (change) in the constructor or static block.
Wartość zostanie odzwierciedlona podczas używania w blokach klasy nadrzędnej
jeśli zmienna jest statyczna, zmień jej wartość podczas samej inicjalizacji za pomocą bloku statycznego,
albo zmień konstruktora.
Możesz także zmienić wartość później w dowolnych blokach. Znajdzie to odzwierciedlenie w super klasie
źródło
class Son extends Dad { static { me = 'son' } }
Krótko mówiąc, nie, nie ma możliwości przesłonięcia zmiennej klasy.
Nie zastępujesz zmiennych klasowych w Javie, ukrywasz je. Przesłanianie dotyczy na przykład metod. Ukrywanie różni się od zastępowania.
W podanym przykładzie, deklarując zmienną klasy o nazwie „ja” w klasie Syn, ukrywasz zmienną klasową, którą odziedziczyłaby po swojej superklasie Tata o tej samej nazwie „ja”. Ukrycie zmiennej w ten sposób nie wpływa na wartość zmiennej klasy „ja” w nadklasie Tata.
W drugiej części twojego pytania, jak sprawić, by wypisał "syn", ustawiłbym wartość za pomocą konstruktora. Chociaż poniższy kod bardzo różni się od pierwotnego pytania, napisałbym go mniej więcej tak;
JLS podaje dużo więcej szczegółów na temat ukrywania w sekcji 8.3 - Deklaracje pól
źródło
Person
ma zastąpić w tym przykładzie?Son
iDad
mają dziedziczyć zPerson
, a następnie wywołaćsuper("Son or Dad");
ich konstruktory.Tak, po prostu zastąp
printMe()
metodę:źródło
printMe()
metody, a nawet ma tę metodę, że jest metodą statyczną?Możesz utworzyć metodę pobierającą, a następnie zastąpić ją. Jest to szczególnie przydatne, jeśli zmienna, którą nadpisujesz, jest samą w sobie podklasą. Wyobraź sobie, że Twoja superklasa ma
Object
członka, ale w Twojej podklasie jest to teraz bardziej zdefiniowane jakoInteger
.źródło
Jeśli masz zamiar go zastąpić, nie widzę żadnego uzasadnionego powodu, aby zachować to statyczne. Sugerowałbym użycie abstrakcji (patrz przykładowy kod). :
Teraz możemy dodać tatę:
syn:
a tata spotkał miłą panią:
Wygląda na to, że mamy rodzinę, powiedzmy światu ich imiona:
}
System.out Wyjście: Tommy Nancy Dad
System.err jest taki sam jak powyżej (ma tylko czerwoną czcionkę)
JOption Wyjście:
Tommy, następnie
Nancy, a następnie
Dad
źródło
To wygląda na błąd konstrukcyjny.
Usuń słowo kluczowe static i ustaw zmienną, na przykład w konstruktorze. W ten sposób Son po prostu ustawia zmienną na inną wartość w swoim konstruktorze.
źródło
Chociaż prawdą jest, że zmienne klasowe mogą być ukryte tylko w podklasach i nie mogą być nadpisywane, nadal można robić, co chcesz, bez nadpisywania
printMe ()
w podklasach, a odbicie jest twoim przyjacielem. W poniższym kodzie pomijam obsługę wyjątków dla przejrzystości. Zwróć uwagę, że zadeklarowanieme
jakoprotected
nie wydaje się mieć większego sensu w tym kontekście, ponieważ będzie ukryte w podklasach ...źródło
... wypisze „syn”.
źródło
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
Nazywa się Hiding Fields
Z linku powyżej
źródło
tylko przez nadpisanie
printMe()
:odwołanie do
me
wDad.printMe
metodzie niejawnie wskazuje na pole statyczneDad.me
, więc w taki czy inny sposób zmieniasz to, coprintMe
robi wSon
...źródło
Nie można przesłonić zmiennych w klasie. Możesz przesłonić tylko metody. Powinieneś zachować zmienne jako prywatne, w przeciwnym razie możesz mieć wiele problemów.
źródło
Rzeczywiście drukuje „tato”, ponieważ pole nie jest nadpisane, ale ukryte. Istnieją trzy sposoby, aby wydrukować słowo „syn”:
Podejście 1: zastąp printMe
Podejście 2: nie ukrywaj pola i inicjalizuj go w konstruktorze
Podejście 3: użyj wartości statycznej, aby zainicjować pole w konstruktorze
źródło
Zmienne nie biorą udziału w nadpisywaniu. Tylko metody. Wywołanie metody jest rozwiązywane w czasie wykonywania, to znaczy decyzja o wywołaniu metody jest podejmowana w czasie wykonywania, ale zmienne są ustalane tylko w czasie kompilacji. Stąd ta zmienna jest wywoływana, której odwołanie jest używane do wywoływania, a nie obiektu wykonawczego.
Spójrz na następujący fragment:
Po uruchomieniu kodu konsola pokaże:
źródło
Oczywiście używanie atrybutów prywatnych oraz metody pobierające i ustawiające byłoby zalecane, ale przetestowałem następujące elementy i działa ... Zobacz komentarz w kodzie
Więc ... czy właśnie przedefiniowałem zasady dziedziczenia, czy postawiłem Oracle w trudnej sytuacji? Dla mnie chroniona statyczna wartość String me jest wyraźnie nadpisywana, co widać po uruchomieniu tego programu. Nie ma też dla mnie sensu, dlaczego atrybuty nie powinny być nadrzędne.
źródło
Dlaczego miałbyś chcieć przesłonić zmienne, skoro można łatwo ponownie przypisać je w podklasach.
Podążam za tym wzorcem, aby obejść projekt języka. Załóżmy, że masz w swoim frameworku ważną klasę usług, która musi być używana w różnych smakach w wielu aplikacjach pochodnych. W takim przypadku najlepszym sposobem skonfigurowania logiki superklasy jest ponowne przypisanie jej zmiennych definiujących.
źródło
Nie. Zmienne klasowe (mają również zastosowanie do zmiennych instancji) nie mają funkcji przesłaniającej w Javie, ponieważ zmienne klasowe są wywoływane na podstawie typu wywoływanego obiektu. Dodano jeszcze jedną klasę (człowiek) w hierarchii, aby była bardziej przejrzysta. Więc teraz mamy
Syn przedłuża Tata przedłuża Człowieka
W poniższym kodzie próbujemy iterować po tablicy obiektów Human, Dad i Son, ale we wszystkich przypadkach wyświetla on wartości Human Class, ponieważ typ wywołującego obiektu to Human.
Wydrukuje
Jeśli chcemy uzyskać dostęp do zmiennej klasy rzeczywistego obiektu ze zmiennej referencyjnej jego klasy nadrzędnej, musimy wyraźnie powiedzieć o tym kompilatorowi, rzutując referencję nadrzędną (obiekt ludzki) na jego typ.
Wydrukuje
O tym, jak część tego pytania: - Jak już sugerowano, przesłonić metodę printMe () w klasie Son, a następnie wywołać
Zmienna klasy Dad „me” zostanie ukryta, ponieważ najbliższa deklaracja (z metody printme () klasy Son) elementu „me” (w klasie Son) będzie miała pierwszeństwo.
źródło
Po prostu wywołaj super.variable w konstruktorze podklasy
Wyjście to 10.
źródło