lekcje 24 i 25 i polimorfizm

Dyskusje na temat języka C# oraz biblioteki .NET
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

lekcje 24 i 25 i polimorfizm

Post przez Zeman »

Witam.

Tylko takie drobne spostrzezenie - lekcja 24 opisuje rzutowanie, operatory as, is, ale nie polimorfizm. Polimorfizm jest opisany dopiero w lekcji 25, moze to niektore osoby wprowadzic w blad, moga zle zrozumiec co to jest polimorfizm.

Generalnie, to dobra robota, dobrze sie slucha i oglada, dosc wygodna nauka. Brawo.
Morfidon
Administrator
Administrator
Posty: 1332
Dołączył(a): wtorek, 5 sierpnia 2008, 21:48
Contact:

Re: lekcje 24 i 25 i polimorfizm

Post przez Morfidon »

Polimorfizm ma wiele swoich odpowiedników...
Istotą polimorfizmu jest to aby to system decydował o szczegółach, nie programista. Przez system należy tu rozumieć kompilator i system czasu wykonania.
źródło

Przy przypisaniu do zmiennej typu klasy bazowej instancji klasy pochodnej to kompilator domyśla się, że można to zrobić. On sam zabrał odpowiedzialność za to, aby domyślić się i sprawdził, że klasa bazowa jest rzeczywiście bazowa dla klasy pochodnej. Gdyby nie był to polimorfizm, istniałaby specjalna operacja wymagana z góry, którą musielibyśmy wykonywać zawsze, ta operacja nie wykonywałaby się "przez domysł" kompilatora.

To jest prosty opis, który Ci podałem polimorfizmu inkluzyjnego.

Pozdrawiam :)
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

Re: lekcje 24 i 25 i polimorfizm

Post przez Zeman »

Faktycznie, wg definicji wikipedii samo juz dziedziczenie jest polimorfizmem, tzn wystarczy zwykle przypisanie instancji potomka do zmiennej rodzica i juz. Nawet wiecej, wg wiki wlasciwie kazde rzutowanie bedzie polimorfizmem, w takim razie np int zrzutuje na iunt i jest polimorfizm :o (nie wiem czy akurat C# na to pozwoli, nie sprawdzalem) Zawsze sie czegos nowego czlowiek nauczy. Zawsze polimorfizm utozsamialem z metodami wirtualnymi, czyli ze jak wywoluje metode obiektu to wywola sie metoda z klasy uzytej podczas konstruktora a nie wskazanej jako typ zmiennej. No i mozna posunac sie dalej.. konstrukcja typu (nie pamietam juz skladni C, wiec moge zle napisac, ale a i b maja byc wskaznikami na char, byte)

Code: Zaznacz cały

char *a; // <- wskaznik na a
byte *b; // <- wskaznik na b

...
b = a; // a i b wskazuja na ten sam bajt
no i teraz moge traktowac ten bajt pamieci jako char przez zmienna a albo jako byte przez zmienna b... no i co - to tez jest polimorfizm :shock: ?
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

Re: lekcje 24 i 25 i polimorfizm

Post przez Zeman »

dla odmiany jakis tam pierwszy lepszy wyklad wygooglany utozsamia polimorfizm z wirtualnoscia metod

http://edu.pjwstk.edu.pl/wyklady/pro/sc ... #dzie:wirt

kazdy inaczej.. wiki wydaje sie miec wiekszy priorytet niz wyklad.
Morfidon
Administrator
Administrator
Posty: 1332
Dołączył(a): wtorek, 5 sierpnia 2008, 21:48
Contact:

Re: lekcje 24 i 25 i polimorfizm

Post przez Morfidon »

Zeman napisał(a):Faktycznie, wg definicji wikipedii samo juz dziedziczenie jest polimorfizmem, tzn wystarczy zwykle przypisanie instancji potomka do zmiennej rodzica i juz.
Dziedziczenie to nie przypisanie instancji potomka do zmiennej rodzica.
Zeman napisał(a):

Code: Zaznacz cały

char *a; // <- wskaznik na a
byte *b; // <- wskaznik na b

...
b = a; // a i b wskazuja na ten sam bajt
Nie ma czegoś takiego jak wskaźnik "na a". Zapis char *a; oznacza: stwórz zmienną o nazwie "a" i zarezerwuj dla niej miejsce w pamięci. Wartość jaką może przechowywać ta zmienna to adres zmiennej typu char

Może to trochę nie na temat, ale wolałem poprawić, aby nie było nieścisłości ;)
Zeman napisał(a):dla odmiany jakis tam pierwszy lepszy wyklad wygooglany utozsamia polimorfizm z wirtualnoscia metod
Bo to jest najlepszy przykład tak jak i np. overloading funkcji: na podstawie przysłanych argumentów kompilator SAM decyduje co ma zrobić :) Najważniejsze zdanie dotyczące polimorfizmu to
Istotą polimorfizmu jest to aby to system decydował o szczegółach, nie programista. Przez system należy tu rozumieć kompilator i system czasu wykonania.
oraz fakt, że jedna nazwa(morph) może znaczyć tak wiele (poli).
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

Re: lekcje 24 i 25 i polimorfizm

Post przez Zeman »

Morfidon napisał(a):
Zeman napisał(a):Faktycznie, wg definicji wikipedii samo juz dziedziczenie jest polimorfizmem, tzn wystarczy zwykle przypisanie instancji potomka do zmiennej rodzica i juz.
Dziedziczenie to nie przypisanie instancji potomka do zmiennej rodzica.
No tak, to wiadomo ze nie to samo.
Morfidon napisał(a):
Zeman napisał(a):

Code: Zaznacz cały

char *a; // <- wskaznik na a
byte *b; // <- wskaznik na b

...
b = a; // a i b wskazuja na ten sam bajt
Nie ma czegoś takiego jak wskaźnik "na a". Zapis char *a; oznacza: stwórz zmienną o nazwie "a" i zarezerwuj dla niej miejsce w pamięci. Wartość jaką może przechowywać ta zmienna to adres zmiennej typu char

Może to trochę nie na temat, ale wolałem poprawić, aby nie było nieścisłości ;)
No tak, powinno byc samo "wskaznik" albo "wskaznik na zmienna typu char / byte", przejezyczenie, ale podejrzewam ze wiadomo o co mi chodzi.. Przyklad pokazuje sytuacje, ze zmienne a i b wskazuja na te sama komorke w pamieci, czyli odnosza sie do tej samej wartosci tylko z innym potraktowaniem w sensie typu. Teraz wg wikipedii moim zdaniem to sie tez zalicza do polimorfizmu
http://pl.wikipedia.org/wiki/Polimorfiz ... rzutowanie
cytat z Wikipedii napisał(a):Wszelkiego rodzaju zmiany typów, zarówno jawne jak i niejawne, statyczne i dynamiczne, również należy uznać za mechanizmy polimorficzne, gdyż pozwalają traktować wartości i zmienne jednego typu, tak jakby były wartościami innego typu.
Morfidon napisał(a):
Zeman napisał(a):dla odmiany jakis tam pierwszy lepszy wyklad wygooglany utozsamia polimorfizm z wirtualnoscia metod
Bo to jest najlepszy przykład tak jak i np. overloading funkcji: na podstawie przysłanych argumentów kompilator SAM decyduje co ma zrobić :) Najważniejsze zdanie dotyczące polimorfizmu to
Istotą polimorfizmu jest to aby to system decydował o szczegółach, nie programista. Przez system należy tu rozumieć kompilator i system czasu wykonania.
Jeszcze raz - pod wskazanym linkiem mozna przeczytac:
cytat z linka z wykladem napisał(a): Dla znających Pythona czy Javę może to być zaskoczenie. Tam bowiem, jak w większości języków obiektowych, decyduje typ dynamiczny: jeśli obiekt, na rzecz którego wywołujemy metodę, jest klasy pochodnej względem tej, która jest typem statycznym wskaźnika (odniesienia) do tego obiektu, to wywołana będzie wersja tej metody pochodząca z klasy pochodnej (jeśli została tam przedefiniowana). Mówimy wtedy, że metody są wirtualne. A zatem w Javie wszystkie metody (prócz finalnych i prywatnych) są wirtualne. Klasy w których istnieją metody wirtualne, nazywamy klasami polimorficznymi, bo wywołanie ich poprzez wskaźnik (odniesienie) pewnego typu zależy od typu obiektu na który ten wskaźnik wskazuje, ma zatem „wiele kształtów”. A zatem w Javie klasy, prócz finalnych, są polimorficzne.

Trzeba jednak zdawać sobie sprawę, że ceną za polimorfizm jest pewna utrata wydajności. Dla wywołań na rzecz obiektów klas niepolimorficznych odpowiednia metoda jest wybierana już w czasie kompilacji na podstawie typu statycznego. Mówimy, że następuje wtedy wczesne wiązanie (ang. early binding).

Typ dynamiczny obiektu wskazywanego przez wskaźnik lub odniesienie może być natomiast określony dopiero w czasie wykonania. Kompilator, napotkawszy wywołanie metody z klasy polimorficznej, nie może umieścić w pliku wykonywalnym kodu odpowiadającego wywołaniu konkretnej funkcji. Zamiast tego umieszczany jest tam kod sprawdzający prawdziwy typ obiektu i wybierający odpowiednią metodę. Mówimy, że następuje wtedy późne wiązanie (ang. late binding). Tak więc każde wywołanie metody wirtualnej powoduje narzut czasowy w trakcie wykonania. Wybranie odpowiedniej metody wymaga też dostępu do informacji o różnych wersjach metody w klasach dziedziczących. Informacja ta jest zwykle umieszczana w specjalnej tablicy, której adres jest przechowywany w każdym obiekcie klasy polimorficznej. Obiekt taki musi być zatem większy niż obiekt analogicznej klasy niepolimorficznej - polimorfizm powoduje zatem również narzut pamięciowy.

W C++, przede wszystkim właśnie ze względu na wydajność, podejście do polimorfizmu jest nieco inne niż w większości innych języków obiektowych. Jako programiści mamy mianowicie możliwość wyboru: czy chcemy, aby definiowana klasa była polimorficzna, czy też z polimorfizmu rezygnujemy na rzecz podniesienia wydajności. Domyślnie nowo definiowane klasy nie są polimorficzne, a zatem definiowane w nich metody nie są wirtualne. Jeśli w programie następuje wywołanie, poprzez wskaźnik lub odniesienie, dowolnej metody na rzecz obiektu klasy niepolimorficznej, kompilator umieszcza od razu wywołanie konkretnej metody w kodzie wynikowym. Kieruje się przy tym wyłącznie typem zadeklarowanym (statycznym) wskaźnika lub odniesienia.

Aby definiowana klasa była polimorficzna, wystarczy jeśli choć jedna metoda tej klasy będzie wirtualna. W szczególności może to być destruktor (ale nie konstruktor - ten wirtualny nie może być nigdy).
Zaznaczylem czerwonym fragmenty swiadczace o tym, ze klasa bez metod wirtualnych nie jest polimorficzna - jest to napisane wprost. Jest tez mowa o poznym wiazaniu i tablicy VMT, o tym, ze w C++ mamy do wyboru czy chcemy wydajnosc czy polimorfizm.

Code: Zaznacz cały

class A {
  public test() { wypiszNaEkran("Jestem z A"); }
}
class B : A {
  new public test() { wypiszNaEkran("Jestem z B"); }
}
...
A zmienna = new B();
zmienna.test();  // wypisze Jestem z A, bo metoda nie jest wirtualna, a typ zmiennej to A (wczesne wiazanie)
((B)zmienna).test();  // wypisze Jestem z B, bo my jawnie wymusilismy to na kompilatorze, typ znany podczas kompilacji (wczesne wiazanie) i nie ma zagladania do VMT

(nie kompilowalem powyzszego, wiec moze byc literowka, ale mam nadzieje ze zamysl jest jasny)

teraz wg wiki jest to polimorfizm a wg wykladu obie klasy nie sa polimorficzne.
Szczerze mowiac to takie troche sprzeczne, bo niby stosujemy polimorfizm stosujac klase nie polimorficzna. Jedyne wytlumaczenie jest takie, ze mozna stosowac polimorfizm recznie poza klasa nawet na klasie ktora nie jest polimorficzna, czyli programista jawnie rzutuje, ale to wszystko powoduje ustalenie metody na poziomie kompilacji i nie ma poznych wiazan. Szczerze mowiac troche zglupialem juz teraz. Tylko wtedy po co klasa sie nazywa nie polimorficzna :D
Morfidon napisał(a):
oraz fakt, że jedna nazwa(morph) może znaczyć tak wiele (poli).
[/quote]

ciezko tu mowic o jednej nazwie bo niby faktycznie ta sama nazwa ale jedna bez rzutowania a druga polaczona z rzutowaniem, czyli taka srednio ta sama.
W Delphi mozna bylo nawet wymusic rzutowanie na niezgodny typ:

Code: Zaznacz cały

(z pamieci)

A = class
   procedure Test;
end;
B = class
   procedure Test;
end;

...
var c: A;
 c:= B(A.Create);
// a jak powyzsze nie przejdzie to zastosowac jeszcze rzutowanie na pointer, bo nie pamietam czy to przejdzie
c.Test;
i teraz uwaga - B nie dziedziczy po A. Powyzsze przejdzie, bo A i B maja tego samego przodka TObject i metoda A.Test bedzie miala ten sam offset wzgledem klasy co B.Test bo sie skompiluje tak samo - jako pierwsza metoda w klasie ;) (pomijam juz oczywistosc ze tak sie nie robi)
Niby tez nazwa taka sama ale tez jak sie uprzemy mozemy zrzutowac. no i teraz wg wiki rzutowalismy a skoro tak to jest to polimorfizm :lol:
Ba, nawet nazwa nie musi byc ta sama:

Code: Zaznacz cały


A = class
   procedure TestAAA;
end;
B = class
   procedure TestBBB;
end;

...
var c: A;
 c:= B(A.Create);
// a jak powyzsze nie przejdzie to zastosowac jeszcze rzutowanie na pointer, bo nie pamietam czy to przejdzie
c.TestAAA;
No i stworzylismy instancje B a zrzutowalismy na cos calkiem innego - na A i jeszcze metoda jest inna.

Pozdrawiam
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

Re: lekcje 24 i 25 i polimorfizm

Post przez Zeman »

Ha, a w technologii COM i pochodnych, typu CORBA / automatyzacja OLE mamy biblioteke typow i tam odwolanie do metody jest jeszcze pozniejsze niz w przypadku zwyklych metod wirtualnych. OMG ale by sie tego uzbieralo. Mozna by stworzyc dluga liste przypadkow i kazac komus okreslic ktore z nich wykorzystuja polimorfizm.
Morfidon
Administrator
Administrator
Posty: 1332
Dołączył(a): wtorek, 5 sierpnia 2008, 21:48
Contact:

Re: lekcje 24 i 25 i polimorfizm

Post przez Morfidon »

Zaznaczylem czerwonym fragmenty swiadczace o tym, ze klasa bez metod wirtualnych nie jest polimorficzna - jest to napisane wprost. Jest tez mowa o poznym wiazaniu i tablicy VMT, o tym, ze w C++ mamy do wyboru czy chcemy wydajnosc czy polimorfizm.
Bo klasa bez metod wirtualnych nie jest polimorficzna i jest to również zgodne z tym co masz napisane na wikipedi. Jedyny temat omówiony w tym wykładzie to temat polimorfizmu dotyczący wyboru wywołania z wielu metod(poli) jednej odpowiedniej, która jednak nazywa się tak samo (morph) (dzieje się to "po cichu" - dzięki kompilatorowi).

To, że nie pisze o innych przykładach polimorfizmu, nie znaczy że one nie są polimorficznymi.

Odnośnie przykładu z c++, który podałeś, klasy może nie są polimorficzne, ale przypisanie jest polimorficzne (w końcu na to kompilator zezwolił, domyślił się...).

Jestem trochę sceptycznie nastawiony do stwierdzenia z wiki:
Wszelkiego rodzaju zmiany typów, zarówno jawne jak i niejawne, statyczne i dynamiczne, również należy uznać za mechanizmy polimorficzne, gdyż pozwalają traktować wartości i zmienne jednego typu, tak jakby były wartościami innego typu.
Uważam, że niejawne, można by było podciągnąć, ale w jawnych w sumie sami dokonaliśmy wyboru za kompilator co przeczy się z stwierdzeniem wyżej:
Istotą polimorfizmu jest to aby to system decydował o szczegółach, nie programista. Przez system należy tu rozumieć kompilator i system czasu wykonania.
Co oznacza, że trochę nie trzyma się definicja "całości". Myślę, że najważniejsze w polimorfizmie jest fakt, aby coś dzięki temu samemu morph miało dostęp do ew. poli rzeczy, a wybór powinien być ostatecznie dokonany przez ??????
W sumie przyglądając się na samo słowo polimorfizm nie ma w niej żadnej informacji na temat kto ma dokonać wyboru, więc możliwe, że zacznę być zgodny z tym, że wybór może być dokonany przez kogokolwiek, chyba że sprecyzujemy dokładnie PODTYP polimorfizmu.

Z wiki wychodzi, że są trochę co do tego niezgodni, czy wybór może być dokonany przez kompilator, przez programistów (nas), czy też obu na raz.

Właściwie można by tu dopatrzeć się takiego samego "błędu" jaki zauważyłem w fizyce dotyczący pojęcia "praca".

Mówi się, że jak ktoś idzie i trzyma np. jakąś teczkę to jego ręce nie wykonują pracy, ponieważ mamy kąt 90 stopni pomiędzy wektorem siły, a wektorem przesunięcia. Owszem może nie wykonują pracy w sensie ruchu, ale ręce wykonują pracę statyczną, w końcu się pocimy i tracimy energię, ba nawet gdybyśmy stali w miejscu... a w końcu wykonana praca to w pewnym sensie energia...

Jednak reasumując to przyjęło się, że praca w fizyce od razu (domyślnie) tyczy się pracy wykonanej dzięki sile * przemieszczenie * cos (kąt między siłą, a przesunięciem)

Teraz trzeba by było się zastanowić jakiego podtypu tyczy się polimorfizm domyślnie.
Zeman
Początkujący
Początkujący
Posty: 7
Dołączył(a): czwartek, 20 października 2011, 11:03

Re: lekcje 24 i 25 i polimorfizm

Post przez Zeman »

Wczoraj jeszcze znalazlem taki link http://4programmers.net/Java/Polimorfizm
Co do niescislosci albo niejednoznacznosci definicji to juz sie spotkalem z wieloma przykladami w IT i poza IT (chocby przyklad z COM - wiele osob (takze definicji w necie) utozsamia je z klasami majacymi biblioteke typow, a w klasyku, ksiazce Programowanie COM w Delphi COM to klasa implementujaca interfejs z GUIDem) no i teraz tu mi tez szkoda czasu na dochodzenie do prawdy. Tak samo juz sobie daruje dalsze dywagacje na temat polimorfizmu, bo sie robi rozmowa troche akademicka / filozoficzna, nie az tak znowu istotna. Najwazniejsze jest to co w praktyce co i jak sie faktycznie stosuje a jak sie to wlasciwie dokladnie nazywa ze wszystkimi szczegolikami. Inny przyklad postac normalna w bazach.. no fajnie jak sie zna formalna definicje ale jak dla mnie rownie cenne jest, jak ktos poprostu stosuje te zasady, chocby nieswiadomie (tak jak ja to robilem przez wiele lat). Tak samo mialem ostatnio test u potencjalnego pracodawcy z Oracla gdzie bylo trzeba przykladowo wybrac ktore skladnie sa prawidlowe TABELA {id-integer, imie-varchar2(20), wiek integer} i teraz
insert into TABELA values(100, 'x', 4)
insert into TABELA values('100', 'x', 4)
akurat wiem, ze Oracle przyjmie tez '100' jako inta bo przypadkiem kiedys tak napisalem, ale do dzis sie zastanawiam co niby maja sprawdzic takie testy.

Pozdrawiam.
Post Reply