Paradygmaty programowania/Ćwiczenia 5: Programowanie obiektowe — przegląd: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Rogoda (dyskusja | edycje)
Nie podano opisu zmian
Wkm (dyskusja | edycje)
 
(Nie pokazano 4 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
===Zadanie 1===
===Zadanie 1===
Co wypisuje poniższy program w języku C++? Odpowiedz, a potem skompiluj program i sprawdź... Uwaga do poprawnego skompilowania programu potrzebne będzie dołączenie pliku nagłówkowego (''#include <iostream>'') i deklaracja przestrzeni nazw (''using namespace std;'').
Co wypisuje poniższy program w języku C++? Odpowiedz, a potem skompiluj program i sprawdź... Uwaga: do poprawnego skompilowania programu potrzebne będzie dołączenie pliku nagłówkowego (#include <iostream>) i deklaracja przestrzeni nazw (using namespace std;).


       ''class A
       class A
       {
       {
         public:
         public:
Linia 9: Linia 9:
         virtual void h() { cout << ”A.h”; }
         virtual void h() { cout << ”A.h”; }
       };
       };
 
     
       class B: public A
       class B: public A
       {
       {
Linia 17: Linia 17:
         virtual void h() { cout << ”B.h”; }
         virtual void h() { cout << ”B.h”; }
       };
       };
 
     
       void main()
       void main()
    {
      {
      A x = B();
        A x = B();
      A* y = new B();
        A* y = new B();
      x.f();
        x.f();
      y–>f();
        y–>f();
       }''
       }


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Pamiętaj, że dynamiczne wiązanie wywołań z metodami następuje tylko wtedy, gdy metoda jest zadeklarowana jako virtual, a instancja obiektu użyta do wywołania jest zaalokowana na stercie.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Pamiętaj, że dynamiczne wiązanie wywołań z metodami następuje tylko wtedy, gdy metoda jest zadeklarowana jako virtual, a instancja obiektu użyta do wywołania jest zaalokowana na stercie.
</div>
</div>
</div>
</div>
===Zadanie 2===
===Zadanie 2===
Jak zmieni się wynik programu z zadania 1, jeśli usuniemy deklarację virtual przy funkcji f w klasie A? Które deklaracje virtual można usunąć bez żadnej zmiany zachowania programu?
Jak zmieni się wynik programu z zadania 1, jeśli usuniemy deklarację virtual przy funkcji f w klasie A? Które deklaracje virtual można usunąć bez żadnej zmiany zachowania programu?
Linia 47: Linia 48:
Przyjrzyj się dwom poniższym klasom. Czy taki układ to dobry pomysł?
Przyjrzyj się dwom poniższym klasom. Czy taki układ to dobry pomysł?


       ''class Silnik {...};
       class Silnik {...};
       class Samochód : Silnik {...};''
       class Samochód : Silnik {...};


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Dziedziczenie powinno pojawiać się tam, gdzie chcemy zdefiniować coś bardziej wyspecjalizowanego. Klasyczne dziedziczenie odpowiada przecież relacji bycia podtypem, czyli relacji „obiekt z podklasy '''jest''' obiektem z klasy bazowej”. W przykładzie z silnikiem i samochodem ta relacja nie zachodzi: obiekt z klasy Samochód ewidentnie nie jest szczególnym przypadkiem obiektu z klasy Silnik. Powiedzielibyśmy natomiast, że (obiekt z klasy) Samochód '''ma''' (obiekt z klasy) Silnik, a w takim razie napisalibyśmy zapewne tak:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Dziedziczenie powinno pojawiać się tam, gdzie chcemy zdefiniować coś bardziej wyspecjalizowanego. Klasyczne dziedziczenie odpowiada przecież relacji bycia podtypem, czyli relacji „obiekt z podklasy '''jest''' obiektem z klasy bazowej”. W przykładzie z silnikiem i samochodem ta relacja nie zachodzi: obiekt z klasy Samochód ewidentnie nie jest szczególnym przypadkiem obiektu z klasy Silnik. Powiedzielibyśmy natomiast, że (obiekt z klasy) Samochód '''ma''' (obiekt z klasy) Silnik, a w takim razie napisalibyśmy zapewne tak:


       ''class Samochód {
       class Samochód {
         Silnik s;
         Silnik s;
         ...
         ...
       };''
       };
</div>
</div>
</div>
</div>
Linia 62: Linia 63:
Popatrz teraz na takie dwie klasy i porównaj ten przykład z sytuacją z poprzedniego zadania.
Popatrz teraz na takie dwie klasy i porównaj ten przykład z sytuacją z poprzedniego zadania.


       ''class Samochód {...};
       class Samochód {...};
       class Ciężarówka : Samochód {...};''
       class Ciężarówka : Samochód {...};


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Te dwie sytuacje stanowią przejrzystą ilustrację różnicy między dziedziczeniem a enkapsulacją...
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Te dwie sytuacje stanowią przejrzystą ilustrację różnicy między dziedziczeniem a enkapsulacją...
</div>
</div>
</div>
</div>
==Test==
<quiz type="exclusive">
Której cechy język obiektowy nie musi posiadać?
<wrongoption reply="Źle">abstrakcyjne typy danych</wrongoption>
<wrongoption reply="Źle">dynamiczne wiązanie wywołań metod z metodami</wrongoption>
<wrongoption reply="Źle">dziedziczenie</wrongoption>
<rightoption reply="Dobrze">podprogramy rodzajowe</rightoption>
</quiz>
<quiz type="exclusive">
Jakie ograniczenie na przedefiniowywanie metod trzeba narzucić
w języku silnie typowanym?
<wrongoption reply="Źle">przedefiniowana metoda musi być bezparametrowa</wrongoption>
<wrongoption reply="Źle">przedefiniowana metoda musi być typu void</wrongoption>
<rightoption reply="Dobrze">przedefiniowana metoda musi zachować taki sam protokół</rightoption>
<wrongoption reply="Źle">nie trzeba narzucać żadnych ograniczeń</wrongoption>
</quiz>
<quiz type="exclusive">
Rozstrzyganie odwołań do bytów o takiej samej nazwie mających definicje w dwóch klasach bazowych odbywa się w C++ za pomocą:
<rightoption reply="Dobrze">operatora \:\: (dwa dwukropki)</rightoption>
<wrongoption reply="Źle">operatora . (kropka)</wrongoption>
<wrongoption reply="Źle">tego nie da się zrobić</wrongoption>
<wrongoption reply="Źle">dziedziczenie wielokrotne nie jest w C++ dozwolone</wrongoption>
</quiz>
<quiz type="exclusive">
W języku C++ obiekty zaalokowane na stosie dealokowane są:
<rightoption reply="Dobrze">niejawnie</rightoption>
<wrongoption reply="Źle">za pomocą delete</wrongoption>
<wrongoption reply="Źle">za pomocą free</wrongoption>
<wrongoption reply="Źle">w C++ nie ma takich obiektów</wrongoption>
</quiz>
<quiz type="exclusive">
Językiem, w którym stosowane jest zawsze dynamiczne wiązanie
wywołań z metodami, jest:
<wrongoption reply="Źle">C++</wrongoption>
<wrongoption reply="Źle">C\#</wrongoption>
<wrongoption reply="Źle">Java</wrongoption>
<rightoption reply="Dobrze">Smalltalk</rightoption>
</quiz>
<quiz type="exclusive">
Językiem, w któym klasa może być samoistna (tzn. nie mieć nadlasy), jest:
<rightoption reply="Dobrze">C++</rightoption>
<wrongoption reply="Źle">C\#</wrongoption>
<wrongoption reply="Źle">Java</wrongoption>
<wrongoption reply="Źle">Smalltalk</wrongoption>
</quiz>
<quiz type="exclusive">
W języku C++ metody, które mają być wiązane dynamicznie, deklaruje się za pomocą:
<wrongoption reply="Źle">operatora -> (strzałka)</wrongoption>
<wrongoption reply="Źle">słowa abstract</wrongoption>
<wrongoption reply="Źle">słowa dynamic</wrongoption>
<rightoption reply="Dobrze">słowa virtual</rightoption>
</quiz>
<quiz type="exclusive">
Który nagłówek poprawnie deklaruje w C++ metodę abstrakcyjną?
<wrongoption reply="Źle">virtual void p();</wrongoption>
<rightoption reply="Dobrze">virtual void p() \=0;</rightoption>
<wrongoption reply="Źle">void p() \=0;</wrongoption>
<wrongoption reply="Źle">abstract void p();</wrongoption>
</quiz>
<quiz type="exclusive">
Klasy "lekkie", deklarowane jako struct, alokowane na stosie i nie
pozwalające na dziedziczenie występują w:
<wrongoption reply="Źle">C++</wrongoption>
<rightoption reply="Dobrze">C\#</rightoption>
<wrongoption reply="Źle">Javie</wrongoption>
<wrongoption reply="Źle">we wszystkich wymienionych tu językach</wrongoption>
</quiz>
<quiz type="exclusive">
Który element nie występuje w JavaScripcie?
<rightoption reply="Dobrze">klasy</rightoption>
<wrongoption reply="Źle">obiekty złożone z par (nazwa własności, wartość)</wrongoption>
<wrongoption reply="Źle">operator new</wrongoption>
<wrongoption reply="Źle">zmienne</wrongoption>
</quiz>

Aktualna wersja na dzień 20:30, 22 wrz 2006

Zadanie 1

Co wypisuje poniższy program w języku C++? Odpowiedz, a potem skompiluj program i sprawdź... Uwaga: do poprawnego skompilowania programu potrzebne będzie dołączenie pliku nagłówkowego (#include <iostream>) i deklaracja przestrzeni nazw (using namespace std;).

     class A
     {
       public:
       virtual void f() { cout << ”A.f”; g(); }
       void g() { cout << ”A.g”; h(); }
       virtual void h() { cout << ”A.h”; }
     };
     
     class B: public A
     {
       public:
       virtual void f() { cout << ”B.f”; g(); }
       void g() { cout << ”B.g”; h(); }
       virtual void h() { cout << ”B.h”; }
     };
     
     void main()
     {
       A x = B();
       A* y = new B();
       x.f();
       y–>f();
     }
Wskazówka:

Zadanie 2

Jak zmieni się wynik programu z zadania 1, jeśli usuniemy deklarację virtual przy funkcji f w klasie A? Które deklaracje virtual można usunąć bez żadnej zmiany zachowania programu?

Wskazówka:

Zadanie 3

Wykorzystanie dynamicznego wiązania wywołań z metodami oznacza, że często będziemy odwoływali się do obiektów z klas pochodnych za pomocą zmiennej (wskaźnika) z klasy bazowej. Jakie są tego konsekwencje dla dealokacji pamięci w językach, w których jest ona jawna? Czy z alokacją jest podobnie?

Wskazówka:

Zadanie 4

Napisz program w Javie, dzięki któremu będzie można zobaczyć, czy i kiedy następuje wywołanie metody finalize. Powinien on dać się uruchomić w różnych wariantach, w których będzie potrzebował mniej lub więcej pamięci.

Zadanie 5

Przyjrzyj się dwom poniższym klasom. Czy taki układ to dobry pomysł?

     class Silnik {...};
     class Samochód : Silnik {...};
Wskazówka:

Zadanie 6

Popatrz teraz na takie dwie klasy i porównaj ten przykład z sytuacją z poprzedniego zadania.

     class Samochód {...};
     class Ciężarówka : Samochód {...};
Wskazówka: