Czy ktoś może podać prosty przykład wyjaśniający różnicę między dynamicznym a statycznym polimorfizmem w Javie?
java
oop
polymorphism
overloading
overriding
Prabhakar Manthena
źródło
źródło
Odpowiedzi:
Wielopostaciowość
1. Statyczne wiązanie / Powiązanie w czasie kompilacji / Wczesne wiązanie / Przeciążenie metod. (W tej samej klasie)
2. Dynamiczne wiązanie / wiązanie w czasie wykonywania / późne wiązanie / zastępowanie metod. (W różnych klasach)
przykład przeciążenia:
nadrzędny przykład:
źródło
Animal reference but Dog object
, dlaczego nie możemy użyćDog reference and dog object
?Przykładem statycznego polimorfizmu byłoby przeciążenie metody
podczas gdy nadpisywanie byłoby przykładem dynamicznego polimorfizmu.
Ponieważ w przypadku przeciążenia, w czasie kompilacji kompilator wie, którą metodę połączyć z wywołaniem. Jednak jest on określany w czasie wykonywania dla dynamicznego polimorfizmu
źródło
Polimorfizm dynamiczny (w czasie wykonywania) to polimorfizm występujący w czasie wykonywania. W tym przypadku kompilator Java nie rozumie, która metoda jest wywoływana w czasie kompilacji. Tylko JVM decyduje, która metoda jest wywoływana w czasie wykonywania. Przeciążanie metod i nadpisywanie metod przy użyciu metod instancji to przykłady dynamicznego polimorfizmu.
Na przykład,
Rozważ aplikację, która serializuje i deserializuje różne typy dokumentów.
Możemy mieć „Dokument” jako klasę bazową i różne klasy typów dokumentów z niego wywodzących się. Np. XMLDocument, WordDocument itp.
Klasa dokumentu definiuje metody „Serialize ()” i „De-serialize ()” jako wirtualne, a każda klasa pochodna zaimplementuje te metody na swój własny sposób w oparciu o rzeczywistą zawartość dokumentów.
W przypadku konieczności serializacji / deserializacji różnych typów dokumentów obiekty dokumentu będą odwoływane przez odwołanie do klasy (lub wskaźnik) oraz w przypadku wywołania metody „Serialize ()” lub „De-serialize ()” na nim wywoływane są odpowiednie wersje metod wirtualnych.
Polimorfizm statyczny (czas kompilacji) to polimorfizm wykazany w czasie kompilacji. Tutaj kompilator Java wie, która metoda jest wywoływana. Przeciążanie metod i nadpisywanie metod przy użyciu metod statycznych; przesłanianie metody przy użyciu metod prywatnych lub końcowych są przykładami polimorfizmu statycznego
Na przykład,
Obiekt pracownika może mieć dwie metody print (), z których jedna nie pobiera argumentów, a druga pobiera przedrostek, który ma być wyświetlany wraz z danymi pracownika.
Biorąc pod uwagę te interfejsy, gdy wywoływana jest metoda print () bez żadnych argumentów, kompilator patrząc na argumenty funkcji wie, która funkcja ma zostać wywołana i odpowiednio generuje kod wynikowy.
Aby uzyskać więcej informacji, przeczytaj „Co to jest polimorfizm” (Google it).
źródło
Ten rysunek wyraźnie pokazuje, co jest wiążące.
Na tym obrazku wywołanie „a1.methodOne ()” wiąże się z odpowiednią definicją methodOne (), a wywołanie „a1.methodTwo ()” jest powiązane z odpowiednią definicją methodTwo ().
Dla każdego wywołania metody powinna istnieć odpowiednia definicja metody. To jest reguła w java. Jeśli kompilator nie widzi właściwej definicji metody dla każdego wywołania metody, zgłasza błąd.
Teraz przejdź do wiązania statycznego i dynamicznego w java.
Statyczne wiązanie w Javie:
.
Wiązanie statyczne można zademonstrować jak na poniższym obrazku.
Na tym rysunku „a1” jest zmienną referencyjną typu klasy A wskazującą na obiekt klasy A. „a2” jest również zmienną referencyjną typu klasy A, ale wskazuje na obiekt klasy B.
Podczas kompilacji, podczas wiązania, kompilator nie sprawdza typu obiektu, na który wskazuje określona zmienna referencyjna. Po prostu sprawdza typ zmiennej referencyjnej, przez którą wywoływana jest metoda i sprawdza, czy istnieje dla niej definicja metody w tym typie.
Na przykład dla wywołania metody „a1.method ()” na powyższym obrazku kompilator sprawdza, czy istnieje definicja metody dla metody method () w klasie A. Ponieważ „a1” jest typem klasy A. Podobnie, dla wywołania metody „a2.method ()” sprawdza, czy istnieje definicja metody dla method () w klasie A. Ponieważ „a2” jest również typem klasy A. Nie sprawdza, na który obiekt wskazuje „a1” i „a2”. Ten typ wiązania nazywany jest wiązaniem statycznym.
Dynamiczne wiązanie w Javie:
W czasie wykonywania do powiązania używane są rzeczywiste obiekty. Na przykład dla wywołania „a1.method ()” na powyższym obrazku zostanie wywołana metoda () rzeczywistego obiektu, na który wskazuje „a1”. Dla wywołania „a2.method ()” zostanie wywołana metoda () rzeczywistego obiektu, na który wskazuje „a2”. Ten typ wiązania nazywa się wiązaniem dynamicznym.
Dynamiczne wiązanie z powyższego przykładu można zademonstrować jak poniżej.
Odwołanie do statycznego wiązania i dynamicznego wiązania w języku Java
źródło
Polimorfizm: Polimorfizm to zdolność obiektu do przyjmowania wielu form. Najbardziej powszechne użycie polimorfizmu w OOP występuje, gdy odwołanie do klasy nadrzędnej jest używane w odniesieniu do obiektu klasy potomnej.
Dynamiczne wiązanie / polimorfizm w czasie wykonywania:
Polimorfizm w czasie wykonywania, znany również jako przesłanianie metody. W tym mechanizmie, za pomocą którego wywołanie nadpisanej funkcji jest rozwiązywane w czasie wykonywania.
Wynik:
Metoda startu wewnętrznego Car
Wiązanie statyczne / polimorfizm w czasie kompilacji:
O wyborze metody decyduje się tylko w czasie kompilacji.
Dane wyjściowe: metoda sortowania kolekcji Inside
źródło
przeciążenie metody jest przykładem czasu kompilacji / statycznego polimorfizmu, ponieważ wiązanie metody między wywołaniem metody a definicją metody ma miejsce w czasie kompilacji i zależy od referencji klasy (referencja utworzona w czasie kompilacji i trafia na stos).
przesłanianie metody jest przykładem wykonywania / dynamicznego polimorfizmu, ponieważ wiązanie metody między wywołaniem metody a definicją metody ma miejsce w czasie wykonywania i zależy od obiektu klasy (obiekt utworzony w czasie wykonywania i trafia na stertę).
źródło
W prostych słowach :
Polimorfizm statyczny : ta sama nazwa metody jest przeciążona innym typem lub liczbą parametrów w tej samej klasie (inny podpis). Wywołanie metody docelowej jest rozwiązywane w czasie kompilacji.
Dynamiczny polimorfizm : ta sama metoda jest zastępowana tym samym podpisem w różnych klasach . Typ obiektu, dla którego wywoływana jest metoda, nie jest znany w czasie kompilacji, ale zostanie określony w czasie wykonywania.
Generalnie przeciążenie nie będzie uważane za polimorfizm.
Ze strony samouczka Java :
źródło
Generally overloading won't be considered as polymorphism.
czy możesz rozwinąć tę kwestię.Przeciążanie metod jest znane jako statyczny polimorfizm, a także znane jako polimorfizm czasu kompilacji lub statyczne wiązanie, ponieważ przeciążone wywołania metod są rozwiązywane w czasie kompilacji przez kompilator na podstawie listy argumentów i odwołania, w którym wywołujemy metodę.
I Metoda Zastępowanie znany jest jako dynamiczna polimorfizmu lub prostego polimorfizmu lub Method Runtime Dispatch czy dynamiczne wiązanie ponieważ przesłonięte wywołanie metody zostanie rozwiązany przy starcie.
Aby zrozumieć, dlaczego tak jest, weźmy przykład
Mammal
iHuman
klasęW poniższych wierszach kodu zawarłem dane wyjściowe oraz kod bajtowy
Patrząc na powyższy kod, widzimy, że kody bajtowe humanMammal.speak (), human.speak () i human.speak („hindi”) są zupełnie inne, ponieważ kompilator jest w stanie je rozróżnić na podstawie listy argumentów i odniesienie do klasy. I właśnie dlatego przeciążanie metod jest znane jako statyczny polimorfizm .
Ale kod bajtowy dla anyMammal.speak () i humanMammal.speak () jest taki sam, ponieważ zgodnie z kompilatorem obie metody są wywoływane w odwołaniu do klasy Mammal, ale dane wyjściowe dla obu wywołań metod są różne, ponieważ w czasie wykonywania JVM wie, jaki obiekt przechowuje odwołanie i wywołuje JVM metoda na obiekcie i dlatego przesłanianie metody jest znane jako dynamiczny polimorfizm.
Tak więc z powyższego kodu i kodu bajtowego jasno wynika, że podczas fazy kompilacji metoda wywołania jest rozważana z typu referencyjnego. Ale w czasie wykonywania metoda zostanie wywołana z obiektu, do którego odwołuje się odwołanie.
Jeśli chcesz dowiedzieć się więcej na ten temat, możesz przeczytać więcej na temat tego, jak JVM obsługuje wewnętrzne przeciążanie i zastępowanie metod .
źródło
Static Polimorphism: to sytuacja, w której decyzja o rozwiązaniu metody do wykonania jest określana w czasie kompilacji. Przykładem może być przeciążanie metod.
Dynamiczny polimorfizm: to sytuacja, w której decyzja o wyborze metody do wykonania jest podejmowana w czasie wykonywania. Przykładem może być przesłanianie metody.
źródło
Polimorfizm odnosi się do zdolności obiektu do zachowania się inaczej dla tego samego wyzwalacza.
Statyczny polimorfizm (polimorfizm w czasie kompilacji)
Dynamiczny polimorfizm (polimorfizm w czasie wykonywania)
źródło
Polimorfizm w czasie kompilacji (wiązanie statyczne / wczesne wiązanie): W polimorfizmie statycznym, jeśli wywołasz metodę w naszym kodzie, wówczas definicja tej metody zostanie wywołana w rzeczywistości tylko w czasie kompilacji.
(lub)
W czasie kompilacji Java wie, którą metodę wywołać, sprawdzając podpisy metod. Nazywa się to więc polimorfizmem w czasie kompilacji lub wiązaniem statycznym.
Dynamiczny polimorfizm (późne wiązanie / polimorfizm w czasie wykonywania): W czasie wykonywania Java czeka do czasu wykonania, aby określić, który obiekt jest faktycznie wskazywany przez odwołanie. Rozwiązanie metody zostało podjęte w czasie wykonywania, dlatego nazywamy go polimorfizmem w czasie wykonywania.
źródło
Rozważ poniższy kod:
Teraz, patrząc na kod, nigdy nie można powiedzieć, która implementacja methodA () zostanie wykonana, ponieważ zależy to od tego, jaką wartość poda użytkownik w czasie wykonywania. Tak więc tylko w czasie wykonywania jest podejmowane decyzje, która metoda zostanie wywołana. Stąd polimorfizm Runtime.
źródło
Przeciążanie metod to polimorfizm czasu kompilacji, weźmy przykład, aby zrozumieć koncepcję.
W tym przykładzie Osoba ma metodę jedzenia, która oznacza, że może zjeść pizzę lub makaron. Że metoda eat jest przeciążona kiedy kompilujemy ten Person.java kompilator rozwiązuje wywołanie metody "e.eat (noodles) [które znajduje się w linii 6] z definicją metody określoną w linii 8 czyli jest to metoda, która przyjmuje makaron jako parametr a cały proces jest wykonywany przez kompilator, więc jest to polimorfizm czasu kompilacji.Proces zamiany wywołania metody na definicję metody jest nazywany wiązaniem, w tym przypadku jest wykonywany przez kompilator, więc jest nazywany wczesnym wiązaniem.
źródło
Kontynuując odpowiedź Naresha, dynamiczny polimorfizm jest „dynamiczny” w Javie tylko ze względu na obecność maszyny wirtualnej i jej zdolność do interpretowania kodu w czasie wykonywania, a nie kodu działającego natywnie.
W C ++ musi być rozwiązany w czasie kompilacji, jeśli jest kompilowany do natywnego pliku binarnego przy użyciu gcc, oczywiście; jednak skok i skok w czasie wykonywania w tabeli wirtualnej są nadal określane jako „wyszukiwanie” lub „dynamiczne”. Jeśli C dziedziczy B, a ty zadeklarujesz
B* b = new C(); b->method1();
, b zostanie rozwiązane przez kompilator w celu wskazania obiektu B wewnątrz C (dla prostej klasy dziedzicza sytuację klasową, obiekt B w C i C rozpocznie się od tego samego adresu pamięci, więc nic jest wymagane; będzie wskazywać na vptr, którego używają oboje). Jeśli C dziedziczy B i A, tablica funkcji wirtualnych obiektu A wewnątrz wpisu C dla metody method1 będzie miała wartość, która przesunie wskaźnik do początku enkapsulującego obiektu C, a następnie przekaże go do rzeczywistej A :: method1 () w segmencie tekstu, który zastąpił C. DlaC* c = new C(); c->method1()
, c będzie już wskazywać na zewnętrzny obiekt C, a wskaźnik zostanie przekazany do C :: metoda1 () w segmencie tekstowym. Zobacz: http://www.programmersought.com/article/2572545946/W Javie
B b = new C(); b.method1();
maszyna wirtualna może dynamicznie sprawdzać typ obiektu sparowanego z b oraz może przekazać poprawny wskaźnik i wywołać poprawną metodę. Dodatkowy krok maszyny wirtualnej eliminuje potrzebę tabel funkcji wirtualnych lub typu rozwiązywanego w czasie kompilacji, nawet jeśli może być znany w czasie kompilacji. Jest to po prostu inny sposób, który ma sens, gdy w grę wchodzi maszyna wirtualna, a kod jest kompilowany tylko do kodu bajtowego.źródło