Dlaczego nie można zastąpić metod statycznych?
Jeśli to możliwe, skorzystaj z przykładu.
java
static
overriding
static-methods
sgokhales
źródło
źródło
Parent p = new Child()
a następniep.childOverriddenStaticMethod()
kompilator rozwiąże toParent.childOverriddenStaticMethod()
, patrząc na typ odwołania.Odpowiedzi:
Przesłonięcie zależy od wystąpienia instancji klasy. Polimorfizm polega na tym, że można podklasować klasę, a obiekty implementujące te podklasy będą miały różne zachowania dla tych samych metod zdefiniowanych w nadklasie (i zastąpionych w podklasach). Metoda statyczna nie jest powiązana z żadnym wystąpieniem klasy, więc koncepcja nie ma zastosowania.
Wpłynęły na to dwie kwestie związane z projektem Javy. Jednym z nich była obawa związana z wydajnością: pojawiła się duża krytyka Smalltalk, ponieważ jest on zbyt wolny (zbieranie śmieci i wywołania polimorficzne są tego częścią), a twórcy Javy byli zdeterminowani, aby tego uniknąć. Kolejną decyzją było to, że docelowymi odbiorcami Javy byli programiści C ++. Sprawienie, by metody statyczne działały w ten sam sposób, co dla programistów C ++, a także bardzo szybkie, ponieważ nie trzeba czekać do czasu wykonania, aby ustalić, którą metodę wywołać.
źródło
objects
) pozwala na przeładowanie metod.obj.staticMethod()
) - co jest dozwolone i wykorzystuje typy czasu kompilacji. Gdy wywołanie statyczne jest metodą niestatyczną klasy, obiekt „bieżący” może być typem pochodnym klasy - ale metody statyczne zdefiniowane na typach pochodnych nie są brane pod uwagę (są w typie wykonawczym hierarchia).Osobiście uważam, że jest to wada w projektowaniu Javy. Tak, tak, rozumiem, że metody niestatyczne są dołączone do instancji, podczas gdy metody statyczne są dołączone do klasy itp. Mimo to rozważ następujący kod:
Ten kod nie będzie działać zgodnie z oczekiwaniami. Mianowicie SpecialEmployee otrzymuje 2% premii, tak jak zwykli pracownicy. Ale jeśli usuniesz „statyczne”, SpecialEmployee dostanie 3% premii.
(Trzeba przyznać, że ten przykład jest kiepskim stylem kodowania, ponieważ w rzeczywistości prawdopodobnie powinieneś chcieć, aby mnożnik premii znajdował się gdzieś w bazie danych, a nie na stałe. Ale to tylko dlatego, że nie chciałem zbytnio bagatelizować przykładu kodu nieistotnego dla sprawy).
Wydaje mi się całkiem prawdopodobne, że możesz ustawić statyczny getBonusMultiplier. Być może chcesz mieć możliwość wyświetlenia mnożnika premii dla wszystkich kategorii pracowników, bez konieczności posiadania instancji pracownika w każdej kategorii. Po co szukać takich przykładów? Co jeśli tworzymy nową kategorię pracowników i nie mamy jeszcze do niej żadnych pracowników? Jest to całkiem logiczna funkcja statyczna.
Ale to nie działa.
I tak, tak, mogę wymyślić dowolną liczbę sposobów przepisania powyższego kodu, aby działał. Nie chodzi mi o to, że stwarza to nierozwiązywalny problem, ale że tworzy pułapkę dla nieostrożnego programisty, ponieważ język nie zachowuje się tak, jak sądzę, że rozsądna osoba by się spodziewała.
Być może gdybym próbował napisać kompilator dla języka OOP, szybko zrozumiałbym, dlaczego implementacja go w celu zastąpienia funkcji statycznych byłaby trudna lub niemożliwa.
A może jest jakiś dobry powód, dla którego Java zachowuje się w ten sposób. Czy ktoś może wskazać zaletę tego zachowania, jakąś kategorię problemu, który jest przez to łatwiejszy? Mam na myśli, nie kieruj mnie tylko do specyfikacji języka Java i powiedz „patrz, to jest udokumentowane, jak się zachowuje”. Wiem to. Ale czy istnieje dobry powód, dla którego POWINIEN się tak zachowywać? (Poza oczywistym „poprawnym działaniem było zbyt trudne” ...)
Aktualizacja
@VicKirk: Jeśli masz na myśli, że jest to „zły projekt”, ponieważ nie pasuje do tego, jak Java obsługuje statykę, moja odpowiedź brzmi: „No cóż, oczywiście.” Jak powiedziałem w moim oryginalnym poście, to nie działa. Ale jeśli masz na myśli, że jest to zły projekt w tym sensie, że byłoby coś zasadniczo nie tak z językiem, w którym to działało, tj. Gdzie statyka mogłaby zostać zastąpiona tak jak funkcje wirtualne, że to w jakiś sposób wprowadziłoby dwuznaczność lub byłoby niemożliwe wydajnie wdrażać lub niektóre takie, odpowiadam: „Dlaczego? Co jest nie tak z tą koncepcją?”
Myślę, że podany przeze mnie przykład jest bardzo naturalny. Mam klasę, która ma funkcję, która nie zależy od danych instancji i którą bardzo rozsądnie chcę wywoływać niezależnie od instancji, a także chcę wywoływać z poziomu metody instancji. Dlaczego to nie powinno działać? Przez lata spotkałem się z tą sytuacją dość często. W praktyce omijam ją, tworząc funkcję wirtualną, a następnie tworząc metodę statyczną, której jedynym celem w życiu jest metoda statyczna, która przekazuje wywołanie do metody wirtualnej za pomocą fałszywej instancji. To wydaje się być bardzo prostym sposobem na dotarcie tam.
źródło
someStatic()
a B rozszerza A, toB.someMethod()
wiąże się z metodą w A. Jeśli następnie dodamsomeStatic()
do B, kod wywołujący nadal wywołuje się,A.someStatic()
dopóki nie skompiluję kodu wywołującego. Zaskoczyło mnie również, żebInstance.someStatic()
używa zadeklarowanego typu bInstance, a nie typu środowiska wykonawczego, ponieważ wiąże się przy kompilacji, a nie z linkiem, dlategoA bInstance; ... bInstance.someStatic()
wywołuje A.someStatic (), jeśli B.someStatic () istnieje.Krótka odpowiedź brzmi: jest to całkowicie możliwe, ale Java tego nie robi.
Oto kod ilustrujący obecny stan rzeczy w Javie:
Plik
Base.java
:Plik
Child.java
:Jeśli uruchomisz to (zrobiłem to na komputerze Mac, z Eclipse, przy użyciu Java 1.6), otrzymasz:
Tutaj jedynymi przypadkami, które mogą być niespodzianką (i których dotyczy pytanie), są pierwsze przypadki:
„Typ wykonawczy nie jest używany do określania, które metody statyczne są wywoływane, nawet jeśli są wywoływane za pomocą instancji obiektu (
obj.staticMethod()
).”i ostatni przypadek:
„Podczas wywoływania metody statycznej z metody obiektowej klasy wybrana metoda statyczna jest dostępna z samej klasy, a nie z klasy definiującej typ obiektu w czasie wykonywania.”
Wywołanie z instancją obiektu
Wywołanie statyczne jest rozwiązywane w czasie kompilacji, natomiast niestatyczne wywołanie metody jest rozwiązywane w czasie wykonywania. Zauważ, że chociaż metody statyczne są dziedziczone (od rodzica), nie są one zastępowane (przez dziecko). To może być niespodzianka, jeśli spodziewałeś się inaczej.
Wywołanie z metody obiektowej
Wywołania metod obiektowych są rozwiązywane przy użyciu typu środowiska wykonawczego, ale wywołania metod statycznych ( klasy ) są rozwiązywane przy użyciu typu deklarowanego (czas kompilacji).
Zmiana zasad
Aby zmienić te reguły, tak aby ostatnie wywołanie w podanym przykładzie wywoływało
Child.printValue()
wywołanie statyczne z typem w czasie wykonywania, zamiast kompilatora rozstrzygającego wywołanie w czasie kompilacji z zadeklarowaną klasą obiektu (lub kontekst). Wywołania statyczne mogłyby następnie użyć (dynamicznej) hierarchii typów do rozwiązania wywołania, podobnie jak obecnie wywoływane są metody obiektowe.Byłoby to łatwo wykonalne (gdybyśmy zmienili Javę: -O) i wcale nie jest nieuzasadnione, ma jednak kilka interesujących względów.
Główną kwestią jest to, że musimy zdecydować, które wywołania metod statycznych powinny to zrobić.
W tej chwili Java ma to „dziwactwo” w języku, w którym
obj.staticMethod()
połączenia są zastępowane przezObjectClass.staticMethod()
połączenia (zwykle z ostrzeżeniem). [ Uwaga:ObjectClass
jest to typ kompilacji w czasieobj
.] Byliby to dobrzy kandydaci do zastąpienia w ten sposób, biorąc pod uwagę typ wykonania w czasie wykonywaniaobj
.Gdybyśmy to zrobili, utrudniłoby to odczytanie treści metod: wywołania statyczne w klasie nadrzędnej mogłyby potencjalnie zostać dynamicznie „przekierowane”. Aby tego uniknąć, musielibyśmy wywołać metodę statyczną z nazwą klasy - a to sprawia, że wywołania są bardziej oczywiste w przypadku hierarchii typów czasu kompilacji (jak teraz).
Inne sposoby wywoływania metody statycznej są trudniejsze:
this.staticMethod()
powinny oznaczać to samo, coobj.staticMethod()
w przypadku wykonania w czasie wykonywaniathis
. Może to jednak powodować pewne problemy z istniejącymi programami, które wywołują (najwyraźniej lokalne) metody statyczne bez dekoracji (co prawdopodobnie jest równoważnethis.method()
).A co z niechcianymi połączeniami
staticMethod()
? Sugeruję, aby robili to samo co dzisiaj i używali lokalnego kontekstu klasowego, aby decydować, co robić. W przeciwnym razie nastąpiłoby wielkie zamieszanie. Oczywiście oznacza to, żemethod()
oznaczałoby to,this.method()
gdybymethod
była to metoda niestatyczna, aThisClass.method()
gdybymethod
była to metoda statyczna. To kolejne źródło zamieszania.Inne uwagi
Jeśli zmieniliśmy to zachowanie (i wykonane połączenia statyczne potencjalnie dynamicznie non-local), prawdopodobnie chcesz ponownie sens
final
,private
aprotected
jako kwalifikatorów nastatic
metodach klasy. Wówczas wszyscy musielibyśmy przyzwyczaić się do faktu, że metodyprivate static
ipublic final
nie są nadpisywane, a zatem mogą być bezpiecznie rozwiązane w czasie kompilacji i są „bezpieczne” do odczytania jako lokalne odniesienia.źródło
Właściwie się myliliśmy.
Mimo że Java domyślnie nie pozwala na przesłonięcie metod statycznych, jeśli dokładnie przejrzysz dokumentację klas Class i Method w Javie, nadal możesz znaleźć sposób na emulowanie metod statycznych zastępujących, stosując następujące obejście:
Wynikowy wynik:
co próbowaliśmy osiągnąć :)
Nawet jeśli zadeklarujemy trzecią zmienną Carl jako RegularEmployee i przypiszemy do niej instancję SpecialEmployee, nadal będziemy mieli wywołanie metody RegularEmployee w pierwszym przypadku i wywołanie metody SpecialEmployee w drugim przypadku
wystarczy spojrzeć na konsolę wyjściową:
;)
źródło
Metody statyczne są traktowane przez JVM jako globalne, w ogóle nie są powiązane z instancją obiektu.
Koncepcyjnie byłoby to możliwe, gdybyś mógł wywoływać metody statyczne z obiektów klasy (jak w językach takich jak Smalltalk), ale nie jest tak w Javie.
EDYTOWAĆ
Możesz przeładować metodę statyczną, w porządku. Ale nie można przesłonić metody statycznej, ponieważ klasa nie jest obiektem pierwszej klasy. Można użyć odbicia, aby uzyskać klasę obiektu w czasie wykonywania, ale otrzymany obiekt nie jest równoległy do hierarchii klas.
Możesz zastanowić się nad klasami, ale na tym się kończy. Nie wywołujesz metody statycznej za pomocą
clazz1.staticMethod()
, ale za pomocąMyClass.staticMethod()
. Metoda statyczna nie jest związana z przedmiotem, a zatem nie ma pojęciathis
anisuper
w metodzie statycznej. Metoda statyczna jest funkcją globalną; w konsekwencji nie ma również pojęcia polimorfizmu, a zatem zastąpienie metody nie ma sensu.Ale byłoby to możliwe, gdyby
MyClass
był obiektem w czasie wykonywania, na którym wywołujesz metodę, tak jak w Smalltalk (lub może JRuby, jak sugeruje jeden komentarz, ale nic nie wiem o JRuby).O tak ... jeszcze jedno. Możesz wywoływać metodę statyczną przez obiekt,
obj1.staticMethod()
ale ten naprawdę składniowy cukier jestMyClass.staticMethod()
i należy go unikać. Zwykle wywołuje ostrzeżenie we współczesnym IDE. Nie wiem, dlaczego kiedykolwiek zezwolili na ten skrót.źródło
clazz2 instanceof clazz1
poprawnie, możesz zamiast tego użyćclass2.isAssignableFrom(clazz1)
, który moim zdaniem zwróciłby prawdę w twoim przykładzie.Nadpisywanie metod jest możliwe dzięki dynamicznemu wywoływaniu , co oznacza, że zadeklarowany typ obiektu nie określa jego zachowania, a raczej jego typ środowiska wykonawczego:
Nawet jeśli oboje
lassie
ikermit
deklarowane są jako obiekty typuAnimal
, ich zachowanie (metoda.speak()
) zmienia się z powodu dynamicznego dyspozytorni będą tylko wiązać wywołanie metody.speak()
do realizacji w czasie wykonywania - nie w czasie kompilacji.Oto, gdzie
static
słowo kluczowe zaczyna mieć sens: słowo „statyczny” jest antonimem słowa „dynamiczny”. Dlatego powodem, dla którego nie można przesłonić metod statycznych, jest to, że nie ma dynamicznego wysyłania elementów statycznych - ponieważ statyczny oznacza dosłownie „niedynamiczny”. Gdyby wysłali dynamicznie (a więc mogliby zostać zastąpieni),static
słowo kluczowe po prostu nie miałoby sensu.źródło
Tak. Praktycznie Java pozwala na przesłonięcie metody statycznej, i teoretycznie, jeśli przesłonisz metodę statyczną w Javie, wówczas kompiluje się i działa płynnie, ale straci polimorfizm, który jest podstawową właściwością Javy. Wszędzie przeczytasz, że nie można spróbować się skompilować i uruchomić. dostaniesz swoją odpowiedź. np. Jeśli masz klasę Animal i metodę statyczną eat () i przesłonisz tę metodę statyczną w jej podklasie, możesz ją nazwać Dog. Następnie, gdziekolwiek przypisujesz obiekt Dog do Animal Reference i wywołujesz eat () zgodnie z Java Dog's eat () powinno być wywoływane, ale w statycznym Overriding Animals's () zostanie wywołane.
Zgodnie z zasadą polimorfizmu Java, wynik powinien być
Dog Eating
.Ale wynik był inny, ponieważ do obsługi polimorfizmu Java używa późnego wiązania, co oznacza, że metody są wywoływane tylko w czasie wykonywania, ale nie w przypadku metod statycznych. W metodach statycznych kompilator wywołuje metody w czasie kompilacji, a nie w czasie wykonywania, więc otrzymujemy metody zgodnie z referencją, a nie z obiektem referencją zawierającą, dlatego można powiedzieć, że praktycznie obsługuje statyczne overring, ale teoretycznie nie „t.
źródło
przesłonięcie jest zarezerwowane dla członków, aby wspierać zachowanie polimorficzne. członkowie klasy statycznej nie należą do określonej instancji. zamiast tego elementy statyczne należą do klasy, w wyniku czego nadpisywanie nie jest obsługiwane, ponieważ podklasy dziedziczą tylko elementy instancji chronionej i publicznej, a nie elementy statyczne. Możesz zdefiniować interfejs i fabrykę badawczą i / lub wzorce projektowe strategii w celu oceny alternatywnego podejścia.
źródło
W Javie (i wielu językach OOP, ale nie mogę mówić za wszystkich, a niektóre w ogóle nie mają statycznego) wszystkie metody mają stałą sygnaturę - parametry i typy. W metodzie wirtualnej sugerowany jest pierwszy parametr: odwołanie do samego obiektu, a po wywołaniu z obiektu kompilator automatycznie dodaje
this
.Nie ma różnicy w przypadku metod statycznych - wciąż mają one stały podpis. Jednak deklarując metodę statyczną, wyraźnie oświadczyłeś, że kompilator nie może zawierać domyślnego parametru obiektu na początku tej sygnatury. Dlatego żaden inny kod, który to wywołuje, nie może próbować umieszczać odwołania do obiektu na stosie . Gdyby to zrobił, wówczas wykonanie metody nie działałoby, ponieważ parametry byłyby w niewłaściwym miejscu - przesunięte o jeden - na stosie.
Z powodu tej różnicy między nimi; metody wirtualne zawsze mają odniesienie do obiektu kontekstu (tj.
this
), więc można odwoływać się do wszystkiego w stercie, które należy do tego wystąpienia obiektu. Jednak w przypadku metod statycznych, ponieważ nie przekazano odwołania, metoda ta nie może uzyskać dostępu do żadnych zmiennych obiektowych i metod, ponieważ kontekst nie jest znany.Jeśli chcesz, aby Java zmieniła definicję, tak aby kontekst obiektowy był przekazywany dla każdej metody, statycznej lub wirtualnej, w istocie miałbyś tylko metody wirtualne.
Jak ktoś zapytał w komentarzu do op - jaki jest powód i cel, dla którego chcesz mieć tę funkcję?
Nie znam dużo Rubiego, ponieważ wspominał o tym PO, przeprowadziłem badania. Widzę, że w klasach Ruby są naprawdę szczególnym rodzajem obiektu i można tworzyć (nawet dynamicznie) nowe metody. Klasy są obiektami pełnej klasy w Rubim, nie są w Javie. Jest to po prostu coś, co musisz zaakceptować podczas pracy z Javą (lub C #). Nie są to języki dynamiczne, chociaż C # dodaje pewne formy dynamiczne. W rzeczywistości Ruby nie ma metod „statycznych”, o ile mogłem je znaleźć - w takim przypadku są to metody obiektu klasy singleton. Następnie możesz zastąpić ten singleton nową klasą, a metody w obiekcie poprzedniej klasy wywołają metody zdefiniowane w nowej klasie (prawda?). Więc jeśli wywołałeś metodę w kontekście oryginalnej klasy, nadal wykonałaby ona tylko oryginalną statykę, ale wywołanie metody w klasie pochodnej wywołałoby metody albo z nadrzędnej, albo z podklasy. Interesujące i widzę w tym pewną wartość. To wymaga innego wzorca myślenia.
Ponieważ pracujesz w Javie, musisz dostosować się do tego sposobu działania. Dlaczego to zrobili? Prawdopodobnie w celu poprawy wydajności w tym czasie w oparciu o dostępną technologię i zrozumienie. Języki komputerowe stale się rozwijają. Wróć wystarczająco daleko i nie ma czegoś takiego jak OOP. W przyszłości pojawią się inne nowe pomysły.
EDYCJA : Jeszcze jeden komentarz. Teraz, gdy widzę różnice i jako sam programista Java / C #, rozumiem, dlaczego odpowiedzi otrzymywane od programistów Java mogą być mylące, jeśli pochodzisz z języka takiego jak Ruby.
static
Metody Java nie są takie same jakclass
metody Ruby . Programiści Java będą mieli trudności ze zrozumieniem tego, podobnie jak ci, którzy pracują głównie z językiem takim jak Ruby / Smalltalk. Widzę, że byłoby to również bardzo mylące, ponieważ Java używa również „metody klasowej” jako innego sposobu mówienia o metodach statycznych, ale Ruby używa tego samego terminu. Java nie ma metod klasy w stylu Ruby (przepraszam); Ruby nie ma metod statycznych w stylu Java, które są tak naprawdę tylko starymi funkcjami w stylu proceduralnym, jak w C.Przy okazji - dziękuję za pytanie! Nauczyłem się dzisiaj czegoś nowego o metodach klasowych (styl Ruby).
źródło
Cóż ... odpowiedź brzmi NIE, jeśli myślisz z perspektywy, jak powinna być zachowana metoda zastępowana w Javie. Jednak przy próbie zastąpienia metody statycznej nie pojawia się błąd kompilatora. Oznacza to, że jeśli spróbujesz przesłonić, Java nie przestanie tego robić; ale z pewnością nie uzyskuje się takiego samego efektu jak w przypadku metod niestatycznych. Przesłonięcie w Javie oznacza po prostu, że konkretna metoda zostanie wywołana na podstawie typu wykonania obiektu, a nie jego typu kompilacji (co ma miejsce w przypadku przesłoniętych metod statycznych). Okej ... jakieś domysły z tego powodu, dlaczego zachowują się dziwnie? Ponieważ są to metody klasowe, dlatego dostęp do nich jest zawsze rozwiązywany w czasie kompilacji tylko przy użyciu informacji o typie czasu kompilacji.
Przykład : spróbujmy zobaczyć, co się stanie, jeśli spróbujemy przesłonić metodę statyczną: -
Wyjście : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
Zwróć uwagę na drugi wiersz wyniku. Gdyby staticMethod zostało zastąpione, linia ta powinna być identyczna z linią trzecią, ponieważ wywołujemy funkcję „staticMethod ()” na obiekcie typu Runtime Type jako „SubClass”, a nie jako „SuperClass”. Potwierdza to, że metody statyczne są zawsze rozwiązywane przy użyciu wyłącznie informacji o typie czasu kompilacji.
źródło
Zasadniczo nie ma sensu zezwalanie na „zastępowanie” metod statycznych, ponieważ nie byłoby dobrego sposobu ustalenia, która z nich ma zostać wywołana w czasie wykonywania. Biorąc przykład pracownika, jeśli wywołamy RegularEmployee.getBonusMultiplier () - która metoda ma zostać wykonana?
W przypadku Javy można sobie wyobrazić definicję języka, w której można „przesłonić” metody statyczne, o ile są one wywoływane przez instancję obiektu. Jednak wystarczyłoby to ponownie wdrożyć metody klasowe, dodając nadmiarowość do języka bez żadnych dodatkowych korzyści.
źródło
Przez przesłonięcie możemy stworzyć naturę polimorficzną w zależności od typu obiektu. Metoda statyczna nie ma związku z przedmiotem. Dlatego Java nie może obsługiwać zastępowania metod statycznych.
źródło
Lubię i podwajam komentarz Jaya ( https://stackoverflow.com/a/2223803/1517187 ).
Zgadzam się, że jest to zły projekt Java.
Wiele innych języków obsługuje nadpisywanie metod statycznych, jak widzimy w poprzednich komentarzach. Czuję, że Jay również przyszedł na Javę z Delphi, tak jak ja.
Delphi (Object Pascal) był pierwszym językiem implementującym OOP.
Oczywistym jest, że wiele osób miało doświadczenie z tym językiem, ponieważ w przeszłości był to jedyny język, w którym pisano komercyjne produkty GUI. I - tak, moglibyśmy w Delphi zastąpić metody statyczne. W rzeczywistości metody statyczne w Delphi są nazywane „metodami klasowymi”, podczas gdy Delphi ma inną koncepcję „metod statycznych Delphi”, które były metodami z wczesnym wiązaniem. Aby zastąpić metody, trzeba było użyć późnego wiązania, zadeklarować dyrektywę „wirtualną”. Było to więc bardzo wygodne i intuicyjne i oczekiwałbym tego w Javie.
źródło
Co dobrego zrobi, aby zastąpić metody statyczne. Nie można wywoływać metod statycznych za pośrednictwem instancji.
EDYCJA: Wygląda na to, że przez niefortunny niedopatrzenie w projektowaniu języka można wywoływać metody statyczne za pomocą instancji. Generalnie nikt tego nie robi. Mój błąd.
źródło
variable.staticMethod()
zamiastClass.staticMethod()
, gdzievariable
jest zmienną o zadeklarowanym typieClass
. Zgadzam się, że to zły projekt językowy.Przesłonięcie w Javie oznacza po prostu, że określona metoda zostanie wywołana na podstawie typu środowiska wykonawczego obiektu, a nie na podstawie typu kompilacji (co ma miejsce w przypadku przesłoniętych metod statycznych). Ponieważ metody statyczne są metodami klasowymi, nie są to metody instancji, więc nie mają one nic wspólnego z faktem, które odniesienie wskazuje na który Obiekt lub instancję, ponieważ ze względu na naturę metody statycznej należy do konkretnej klasy. Możesz zmienić go w podklasie, ale ta podklasa nie będzie wiedziała nic o metodach statycznych klasy nadrzędnej, ponieważ, jak powiedziałem, jest specyficzna tylko dla tej klasy, w której została zadeklarowana. Dostęp do nich za pomocą odwołań do obiektów jest tylko dodatkową swobodą przyznaną przez projektantów Java i z pewnością nie powinniśmy myśleć o zaprzestaniu tej praktyki tylko wtedy, gdy ograniczają ją więcej szczegółów i przykładów http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html
źródło
Przez nadpisanie osiągasz dynamiczny polimorfizm. Kiedy mówisz, że zastępujesz metody statyczne, słowa, których próbujesz użyć, są sprzeczne.
Statyczny mówi - czas kompilacji, nadpisywanie jest używane do dynamicznego polimorfizmu. Oba są z natury przeciwne i dlatego nie można ich używać razem.
Dynamiczne zachowanie polimorficzne pojawia się, gdy programista używa obiektu i uzyskuje dostęp do metody instancji. JRE odwzorowuje różne metody instancji różnych klas w oparciu o rodzaj używanego obiektu.
Kiedy mówisz, że zastępujesz metody statyczne, do metod statycznych uzyskamy dostęp przy użyciu nazwy klasy, która zostanie połączona w czasie kompilacji, więc nie ma koncepcji łączenia metod w środowisku wykonawczym z metodami statycznymi. Sam termin „przesłanianie” metod statycznych nie ma więc żadnego znaczenia.
Uwaga: nawet jeśli uzyskasz dostęp do metody klasy za pomocą obiektu, nadal kompilator Java jest wystarczająco inteligentny, aby go znaleźć, i wykona statyczne łączenie.
źródło
Box.createBox
ma więcej sensuBoxFactory.createBox
i jest nieuniknionym wzorcem, gdy trzeba sprawdzić błąd konstrukcji bez zgłaszania wyjątków (konstruktory nie mogą zawieść, mogą jedynie zabić proces / rzut) wyjątek), podczas gdy metoda statyczna może zwrócić wartość NULL w przypadku niepowodzenia lub nawet zaakceptować wywołania zwrotne sukcesu / błędu, aby napisać coś takiego jak hastebin.com/codajahati.java .Odpowiedź na to pytanie jest prosta, metoda lub zmienna oznaczona jako statyczna należy tylko do klasy, więc tej metody statycznej nie można dziedziczyć w podklasie, ponieważ należą one tylko do superklasy.
źródło
Proste rozwiązanie: użyj instancji singleton. Pozwoli to na zastąpienia i dziedziczenie.
W moim systemie mam klasę SingletonsRegistry, która zwraca instancję dla przekazanej klasy. Jeśli instancja nie zostanie znaleziona, zostanie utworzona.
Klasa językowa Haxe:
źródło
Singleton.get()
. Rejestr jest po prostu narzutem nad głową i wyklucza GC w klasach.Metoda statyczna, zmienna, blokowa lub zagnieżdżona należy do całej klasy a nie do obiektu.
Metoda w Javie służy do ujawnienia zachowania obiektu / klasy. Tutaj, ponieważ metoda jest statyczna (tj. Metoda statyczna jest używana do reprezentowania zachowania tylko klasy). Zmiana / nadpisanie zachowania całej klasy naruszy zjawisko jednego z podstawowych filarów programowania obiektowego, tj. Wysoką spójność . (pamiętaj, że konstruktor jest specjalną metodą w Javie).
Wysoka spójność - jedna klasa powinna mieć tylko jedną rolę. Na przykład: klasa samochodów powinna produkować wyłącznie przedmioty samochodowe, a nie rowery, ciężarówki, samoloty itp. Ale klasa samochodów może mieć pewne cechy (zachowania), które należą tylko do siebie.
Dlatego podczas projektowania języka programowania Java. Projektanci języka pomyśleli, aby pozwolić programistom na zachowanie niektórych zachowań klasy tylko przez uczynienie metody statyczną z natury.
Poniższy kod fragmentu próbuje zastąpić metodę statyczną, ale nie napotka żadnego błędu kompilacji.
Jest tak, ponieważ tutaj nie zastępujemy metody, ale po prostu ją deklarujemy . Java umożliwia ponowną deklarację metody (statyczna / niestatyczna).
Usunięcie słowa kluczowego static z metody getVehileNumber () klasy Car spowoduje błąd kompilacji, ponieważ staramy się zmienić funkcjonalność metody statycznej, która należy tylko do klasy Vehicle.
Ponadto, jeśli getVehileNumber () zostanie zadeklarowany jako końcowy, kod nie zostanie skompilowany, ponieważ ostatnie słowo kluczowe ogranicza programistę przed ponownym zadeklarowaniem metody.
Ogólnie rzecz biorąc, to zależy od projektantów oprogramowania, gdzie można zastosować metody statyczne. Osobiście wolę używać metod statycznych do wykonywania niektórych akcji bez tworzenia instancji klasy. Po drugie, aby ukryć zachowanie klasy przed światem zewnętrznym.
źródło
Oto proste wyjaśnienie. Metoda statyczna jest powiązana z klasą, podczas gdy metoda instancji jest powiązana z określonym obiektem. Przesłonięcia pozwalają na wywołanie innej implementacji przesłoniętych metod powiązanych z danym obiektem. Dlatego sprzeczne z intuicją jest zastępowanie metody statycznej, która nie jest nawet powiązana z obiektami, ale przede wszystkim z samą klasą. Tak więc metod statycznych nie można zastąpić na podstawie tego, który obiekt to wywołuje, zawsze będzie on powiązany z klasą, w której został utworzony.
źródło
public abstract IBox createBox();
wewnętrznego interfejsu IBox jest sprzeczne z intuicją ? Box może zaimplementować IBox w celu zastąpienia createBox, a utworzenie obiektu spowoduje poprawny IBox, w przeciwnym razie zwróci wartość null. Konstruktorzy nie mogą zwracać wartości „null” i dlatego jesteś zmuszony (1) używać wyjątków WSZĘDZIE (co robimy teraz) lub (2) tworzyć klasy fabryczne, które robią to, co powiedziałem wcześniej, ale w sposób, który nie ma sensu dla nowicjuszy ani ekspertów Java (co również robimy teraz). Rozwiązują to statyczne niezaimplementowane metody.Widząc powyższe odpowiedzi, wszyscy wiedzą, że nie możemy przesłonić metod statycznych, ale nie należy źle rozumieć pojęcia dostępu do metod statycznych z podklasy .
Na przykład zobacz poniższy kod: -
Wynik:-
Dzięki
źródło
Poniższy kod pokazuje, że jest to możliwe:
źródło
osm
jest .OverridenStaticMeth
OverrideStaticMeth