Polimorfizm a dziedziczenie: różnica między polimorfizmem a dziedziczeniem [2022]

Opublikowany: 2021-01-05

Polimorfizm i dziedziczenie są bardzo podstawowymi koncepcjami programowania obiektowego. Dodanie obiektów we współczesnych językach programowania znacząco zmieniło sposób, w jaki używamy języka i rzeczy, które jesteśmy w stanie z nimi zrobić. W skrócie, programowanie obiektowe to zestaw metod, które pozwalają programiście na używanie klas, a co za tym idzie, wyprowadzanie obiektów na podstawie tych klas.

Ma na celu upodobnienie się do rzeczywistych jednostek i ułatwienie programistom tworzenia ich kodu zawierającego paradygmat, w którym piszą swój kod. Zasadniczo istnieją cztery koncepcje programowania obiektowego, a mianowicie dziedziczenie, abstrakcja, polimorfizm i enkapsulacja. Teraz każdy z pomysłów, jak wspomniano wcześniej, może być traktowany jako filar, na którym stoi każdy współczesny język.

Wracając do naszego tematu polimorfizmu a dziedziczenia i prawa nietoperza, widzimy rażącą różnicę między tymi dwoma pojęciami. Dziedziczenie to koncepcja, która umożliwia ponowne użycie kodu w tym samym lub innym programie. Możemy nawet zmienić zachowanie kodu, zachowując rzeczy, które nam się podobają, i odrzucając te, które nie są przydatne do zadań, które próbujemy wykonać. Dziedziczenie oszczędza dużo czasu przy opracowywaniu prawie wszystkiego, co widzimy obecnie na naszych wyświetlaczach cyfrowych.

Z drugiej strony polimorfizm odpowiada za dyktowanie kodu, który został już napisany i decydowanie, jaki kod należy wykonać na podstawie określonych parametrów w czasie rzeczywistym. Byłoby korzystne, gdyby każdy najpierw szczegółowo przeanalizował każdą z tych koncepcji, zanim przejdzie do dyskusji na temat różnicy między polimorfizmem a dziedziczeniem. Różnice staną się bardziej wyraźne, gdy dowiemy się, co dokładnie oznacza dziedziczenie i polimorfizm.

Zdobądź stopnie inżynierii oprogramowania z najlepszych światowych uniwersytetów. Zdobywaj programy Executive PG, Advanced Certificate Programs lub Masters Programs, aby przyspieszyć swoją karierę.

Spis treści

Dziedzictwo

Byłoby przestępstwem w paradygmacie programowania nie uznawanie dziedziczenia za bardzo kluczową koncepcję OOP. Nigdy nie należy lekceważyć znaczenia dziedziczenia, ponieważ celem dziedziczenia jest „ponowne wykorzystanie”. Dziedziczenie, jak sugeruje nazwa, polega na tym, że pozwala na rozszerzenie kodu zapisanego w klasie na inną klasę. Tak więc w dziedziczeniu istnieje klasa bazowa; klasa, w której napisany jest kod, ma zostać ponownie wykorzystana.

Następna klasa, którą byśmy stworzyli, musiałaby zostać odziedziczona z tej klasy bazowej, aby korzystać ze wszystkich funkcji i zmiennych związanych z klasą bazową. Za każdym razem, gdy klasa pobiera właściwości innej klasy (lub dziedziczy z innej klasy), wszyscy członkowie, którzy są obecni w klasie bazowej, stają się członkami tej nowej klasy pochodnej.

Przykładowy kod podany poniżej pokaże Ci, jak wygląda ogólna forma dziedziczenia. Jedną z kluczowych rzeczy, na którą należy zwrócić uwagę, jest to, że dokładna składnia, którą musiałbyś napisać, aby umożliwić dziedziczenie kodu, zależałaby wyłącznie od wybranego języka programowania.

  1. class nazwa-klasy pochodnej: specyfikator dostępu nazwa-klasy bazowej {
  2. // ciało klasy pochodnej
  3. }

W powyższym przykładzie pewne rzeczy wymagają niewielkiego wyjaśnienia. Słowo „specyfikator dostępu” oznacza sposób, w jaki klasa pochodna miałaby dostęp do właściwości i metod klasy bazowej. Ogólnie istnieją trzy specyfikatory dostępu, z których każdy ma swoje własne znaczenie (tj. prywatny, publiczny i chroniony) i właściwości.

Ponownie, w zależności od wybranego języka, możesz lub nie musisz używać tych specyfikatorów dostępu. Tak więc w świecie C++, jeśli dziedziczysz bez określania niczego domyślnie, staje się to prywatne. Jeśli jednak dziedziczysz ze struktury (jest to słowo kluczowe struct), domyślnym specyfikatorem dostępu będzie public zamiast private.

Przeczytaj: Możliwości kariery w języku programowania R

C++ daje również wiele opcji do wyboru podczas dziedziczenia. Niektóre z nich znajdziesz poniżej:

a. Dziedziczenie hierarchiczne: Ten rodzaj dziedziczenia jest zgodny z zasadą, że powinna istnieć tylko jedna nadklasa, az tej nadklasy musi być wiele podklas pochodnych. Przykład tego znajdziesz poniżej:

  1. //Klasa bazowa
  2. klasa A
  3. {
  4. public void funA()
  5. {
  6. //
  7. }
  8. }
  9. //Klasy pochodnej
  10. klasa B: A
  11. {
  12. public void funB()
  13. {
  14. //
  15. }
  16. }
  17. //Klasy pochodnej
  18. klasa C: A
  19. {
  20. public void funC()
  21. {
  22. //
  23. }
  24. }
  25. //Klasy pochodnej
  26. klasa D: C
  27. {
  28. publiczny fundusz nieważny()
  29. {
  30. //
  31. }
  32. }
  33. //Klasy pochodnej
  34. klasa E: C
  35. {
  36. public void funE()
  37. {
  38. //
  39. }
  40. }
  41. //Klasy pochodnej
  42. klasa F: B
  43. {
  44. public void funF()
  45. {
  46. //
  47. }
  48. }
  49. //Klasy pochodnej
  50. klasa G: B
  51. {
  52. public void funG()
  53. {
  54. //
  55. }
  56. }

b. Wielokrotne dziedziczenie: Jeśli wykonujesz wielokrotne dziedziczenie, oznaczałoby to, że masz tylko jedną pochodną podklasę, która dziedziczy z wielu nadklas. Poniżej znajdziesz prosty przykład dziedziczenia wielokrotnego:

  1. //Klasa bazowa
  2. klasa A
  3. {
  4. public void funA()
  5. {
  6. //
  7. }
  8. }
  9. //Klasa bazowa
  10. klasa B
  11. {
  12. public void funB()
  13. {
  14. //
  15. }
  16. }
  17. //Klasy pochodnej
  18. klasa C: A, B
  19. {
  20. public void funC()
  21. {
  22. //
  23. }
  24. }

C. Pojedyncze dziedziczenie: jest to prawdopodobnie najprostsza forma dziedziczenia. Istnieje tylko jedna klasa podstawowa i jedna klasa pochodna. Poniżej znajdziesz przykład:

  1. //Klasa bazowa
  2. klasa A
  3. {
  4. public void funA()
  5. {
  6. //DO ZROBIENIA:
  7. }
  8. }
  9. //Klasy pochodnej
  10. klasa B: A
  11. {
  12. public void funB()
  13. {
  14. //DO ZROBIENIA:
  15. }
  16. }

Wielopostaciowość

Podstawowa definicja słowa polimorfizm oznacza posiadanie wielu form. Ta definicja jest bardzo trafna w wyjaśnianiu polimorfizmu w kontekście programowania. W tym paradygmacie polimorfizm przybiera znaczenie jednej funkcji, ale wielu form. Polimorfizm faktycznie zachodzi w czasie kompilacji. Polimorfizm w czasie kompilacji jest możliwy tylko dzięki koncepcji przeciążania, aw czasie wykonywania funkcja przesłaniania czyni polimorfizm rzeczywistością. Jeden po drugim zajmijmy się definicją zarówno przeciążenia, jak i nadpisania.

Przeciążanie wymaga napisania kodu lub funkcji klasy więcej niż raz z różnymi parametrami, ale z tym samym typem zwracania. Oznacza to, że argumenty, które przekazujesz do funkcji, mogą być różne i tylko patrząc na końcowe wartości, które są przekazywane do funkcji w czasie wykonywania, decydujesz, która forma funkcji ma zostać wywołana. Ogólnie rzecz biorąc, widzimy, że konstruktor klasy jest najbardziej przeciążoną funkcją. Cała ta teoria stanie się bardzo jasna i łatwiej będzie ci ją zakorzenić w swoim umyśle za pomocą przykładu.

  1. przeciążenie klas{
  2. wta, b;
  3. publiczny:
  4. int przeciążenie (int x){ // pierwszy konstruktor przeciążenia()
  5. a=x;
  6. zwróć;
  7. }
  8. int przeciążenie (int x, int y){ //drugi przeciążenie() konstruktor
  9. a=x;
  10. b=y;
  11. zwróć a*b;
  12. }
  13. };
  14. int główna (){
  15. przeciążenie O1;
  16. O1. przeciążenie (20); //pierwsze wywołanie konstruktora przeciążenia()
  17. O1. przeciążenie (20,40); // drugie wywołanie konstruktora przeciążenia()

W tym przykładzie widzimy przeciążenie w działaniu. Zobacz, jak wywoływane są różne konstruktory w zależności od tego, czy ostateczna wartość nawiasu obiektu to jedna liczba całkowita, czy dwie.

Zajmijmy się teraz definicją zastępowania. Możesz wykonać zastępowanie tylko tych określonych funkcji, które są dziedziczone. Tak, dziedziczenie jest kluczowym punktem w umożliwieniu zastępowania funkcji. Jeśli chcesz napisać funkcję, a także ją zastąpić, w C++ będziesz musiał użyć słowa kluczowego virtual przed definicją funkcji, aw klasie pochodnej używającej tej samej nazwy dla twojej funkcji, po prostu usuń słowo kluczowe virtual. Aby umocnić twoje zrozumienie, oto przykład:

  1. baza klas{
  2. publiczny:
  3. virtual void funct (){ //wirtualna funkcja klasy bazowej
  4. cout<<“To jest funct() klasy bazowej”;
  5. }
  6. };
  7. klasa pochodna1 : baza publiczna{
  8. publiczny:
  9. void funct (){ //wirtualna funkcja klasy bazowej przedefiniowana w klasie pochodnej1
  10. cout<<“To jest funkcja klasy pochodnej1”;
  11. }
  12. };
  13. wew główna ()
  14. {
  15. podstawa *p, b;
  16. pochodna1 d1;
  17. *p=&b;
  18. p-> funkcja (); //wywołaj funct() klasy bazowej.
  19. *p=&d1;
  20. zwróć 0;
  21. }

Spójrz, jak słowo kluczowe virtual jest używane w klasie bazowej, a w klasie pochodnej ta sama definicja funkcji jest tam, tylko brakuje słowa kluczowego virtual.

Kilka utrzymujących się różnic między polimorfizmem a dziedziczeniem:

  1. Dziedziczenie jest zasadniczo tworzeniem klasy, a następnie posiadanie innych klas w programie pobiera ich cechy z już istniejącej klasy bazowej. Jednak polimorfizm jest interfejsem, a ponieważ jest interfejsem, może przybierać różne kształty i formy.
  2. Dziedziczenie jest właściwością odnoszącą się tylko do klas, podczas gdy polimorfizm rozciąga się na dowolną metodę i/lub funkcję.
  3. Dziedziczenie umożliwia klasie pochodnej używanie wszystkich funkcji i zmiennych zadeklarowanych w klasie bazowej bez ponownego ich jawnego definiowania. Dlatego mówimy, że dziedziczenie zwiększa możliwość ponownego wykorzystania kodu i zmniejsza długość kodu, który musielibyśmy napisać, gdyby nie było dziedziczenia. Natomiast polimorfizm pozwala, aby ta sama nazwa funkcji miała dwa bardzo różne kody. Czyli w pewnym sensie zamiast zmniejszać długość kodu, który musielibyśmy napisać, polimorfizm rozszerza go dalej.
  4. Istnieje wiele form dziedziczenia; możesz być naprawdę kreatywny dzięki dziedziczeniu. Jednak polimorfizm można osiągnąć tylko dwoma sposobami, tj. przeciążeniem i nadpisaniem. Nadal możesz zwariować podczas używania polimorfizmu, ale jesteś ograniczony tylko do dwóch sposobów implementacji go w swoim kodzie pisania.

Musisz przeczytać: Musisz przeczytać 47 OOPS pytań i odpowiedzi do wywiadu dla świeżo upieczonych i doświadczonych

Polimorfizm a dziedziczenie: zróżnicowanie tabelaryczne

W poniższej tabeli znajdziesz wyraźną różnicę między polimorfizmem a dziedziczeniem:

ŚRODKI PORÓWNAWCZE DZIEDZICTWO WIELOPOSTACIOWOŚĆ
Podstawowe różnice między nimi Znaczenie dziedziczenia polega na tworzeniu nowych klas, które posiadają właściwości (funkcje i zmienne istniejących klas) Jest to zasadniczo platforma, która pozwala na pisanie kodu w różnych formach.
Różnice w sposobie, w jaki oba z nich można zintegrować z Twoim kodem Tylko klasy mogą cieszyć się prawdziwym dziedziczeniem w kodzie. Może być zaimplementowany i używany przez dowolne funkcje i/lub metody w całym kodzie.
Różnice w sposobie wykorzystania obu z nich. Umożliwia ponowne użycie napisanego kodu w tym samym lub innym programie. Bez tego programowanie obiektowe nie miałoby kluczowej funkcji. Pozwala to zadeklarowanemu obiektowi podjąć decyzję, która forma funkcji ma zostać wywołana. Można o tym zdecydować dwa razy. W czasie wykonywania nazywa się to nadpisywaniem; w czasie kompilacji nazywa się to przeciążaniem.
Obie formy mogą przybierać różne formy Istnieje mnóstwo form, jakie może przybrać dziedziczenie. Mogą istnieć tylko dwie formy polimorfizmu. W zależności od czasu w programie zmienia się z przeciążenia na nadpisanie.
Podstawowy przykład pokazujący, jak każdy z nich jest zaimplementowany. Rower klasy może dziedziczyć po klasie pojazdów dwukołowych, które z kolei mogą być podklasą pojazdów. Rower klasy może mieć metodę o nazwie set_color(), która zmienia kolor roweru na podstawie nazwy wprowadzonego koloru.

Sprawdź: Co to jest rzutowanie typów w Javie | Zrozumienie rzutowania typu jako początkujący

Wniosek

Można śmiało powiedzieć, że zarówno polimorfizm, jak i dziedziczenie są kluczowymi pojęciami w urzeczywistnianiu dowolnego programu. Oba są fundamentem, na którym zbudowano ideę programowania obiektowego. Istnieje wiele różnic między polimorfizmem a dziedziczeniem, ponieważ służą one dwóm bardzo różnym celom.

Polimorfizm pozwala programiście na pisanie wielu definicji funkcji. Jednocześnie dziedziczenie umożliwia użytkownikowi ponowne wykorzystanie już napisanego kodu. Aby w pełni zrozumieć i docenić te dwie koncepcje, zaleca się dalsze zapoznanie się z obydwoma tematami.

Jedną rzeczą, o której zawsze powinieneś pamiętaćza każdym razem gdy piszesz kod jest toże jeśli chcesz zmienićkod już napisany (zasadniczo definicjęjednej klasy i użyćjej ponownie w swoim kodzie aby obsłużyćpodobny lub inny cel), należy skorzystać z dziedziczenia. Jeśli chcesz zmniejszyć ogólne zamieszanie w kodzie i chcesz używać tej samej nazwy funkcji do wykonywania podobnych zadań, powinieneś użyć polimorfizmu.

Jeśli chcesz dowiedzieć się więcej o tworzeniu pełnego stosu oprogramowania, zapoznaj się z dyplomem PG upGrad i IIIT-B w zakresie pełnego tworzenia oprogramowania, który jest przeznaczony dla pracujących profesjonalistów i oferuje ponad 500 godzin rygorystycznych szkoleń, ponad 9 projektów i zadania, status absolwentów IIIT-B, praktyczne praktyczne projekty zwieńczenia i pomoc w pracy z najlepszymi firmami.

Zaplanuj swoją karierę programistyczną już teraz.

Złóż wniosek o certyfikację PG związaną z pracą w inżynierii oprogramowania