Dziedziczenie Dziedziczenie umożliwia definiowanie nowej klasy przez rozbudowanie już istniejącej. Klasa wprowadzana całkowicie dziedziczy elementy starej klasy.» Dodawanie nowych elementów klasy (składowych funkcyjnych, danych składowych)» Modyfikacje odziedziczonych składowych funkcyjnych
Dziedziczenie Systematyka (gr. systematikos stanowiący układ, system) jest to układ (czyli system) przedmiotów lub pojęć danej nauki, a zarazem także (pod-)dziedzina danej nauki zajmująca się klasyfikowaniem jej przedmiotów i pojęć (czyli inaczej taksonomia). Arystoteles był pierwszym powszechnie znanym systematykiem Systematycy kategoryzują część świata, tworzą hierarchię kategorii od ogólnych do szczegółowych.
Dziedziczenie uogólnione Pojazdy transportowe Pojazd naziemny Pojazd powietrzny Pojazd wodny Samochód Rower Sanki specjalizowane TIR Autobus Samochód dostawczy
Dziedziczenie - Względnie niewielka liczba cech oraz czynności, które mogą być przyporządkowane do ogólnej kategorii - W miarę przesuwania się w dół hierarchii ku bardziej specjalistycznym kategoriom, dołączamy specjalistyczne cechy oraz czynności (nie związane z bardziej ogólnymi kategoriami) - Czytanie w górę jest zawsze prawdziwe relacja JEST KAŻDY ROWER jest POJAZDEM NAZIEMNYM jest prawdziwe ale KAŻDY POJAZD TRANSPORTOWY jest SANKAMI nie.
Dziedziczenie Specyfikacja klasy bazowej w C#: class SportsCar : Car Specyfikacja klasy bazowej w Java: class SportsCar extends Car
Dziedziczenie - przesłanianie class Samochod public virtual void JedzDoPrzodu() //... Metod wirtualna class SamochodSportowy : Samochod public override void JedzDoPrzodu() //...
Dziedziczenie Aby przesłaniania działało prawidłowo: - należy dołączyć słowo virtual w metodzie klasy bazowej - należy dołączyć słowo override w metodzie przesłaniającej Metoda virtual nie może być jednocześnie private Metoda przesłaniająca musi mieć tę samą nazwę, liczbę, sekwencję i typy parametrów. Aby uniemożliwić wykorzystanie klasy jako klasy bazowej, można zadeklarować ją jako zamkniętą (sealed)
Dziedziczenie Słowo kluczowe protected (modyfikator dostępu) zapewnia taki sam poziom dostępu jak private, ale ponadto umożliwia dostęp do danej z klasy z klas z niej wyprowadzonych.
Polimorfizm Technika ściśle związana z dziedziczeniem zwykle uważana za najważniejszą zaletę technologii obiektowych Jeśli do obiektu zostanie wysłany komunikat, to obiekt musi mieć odpowiednią metodę, aby móc odpowiedzieć. W hierarchii dziedziczenia podklasy przejmują interfejsy po swoich nadklasach. Każda klasa jest osobnym bytem, może wymagać innego rodzaju reakcji na ten sam komunikat.
Polimorfizm Shape #area : double +getarea() : double Rectangle -length -width +getarea() : double -radius Circle +getarea() : double Różne zachowanie różne implementacje metod Technologie obiektowe
Kompozycja - Tworzenie obiektów przy pomocy innych obiektów. - Jest rodzajem silnej agregacji całość-część - Relacja kompozycji polega na tym, że: - instancja reprezentująca część należy w danym momencie tylko do jednej instancji złożonej - część musi zawsze należeć do jakiejś całości - instancja złożona jest odpowiedzialna za tworzenie i usuwanie swoich części - po usunięciu instancji złożonej, wszystkie jej części muszą zostać usunięte - Agregacja jest rodzajem kompozycji bez powyższych ograniczeń Zgodnie z wytycznymi twórców UML unikaj stosowania agregacji. Jeśli to możliwe używaj kompozycji Java/.NET jest tylko kompozycja
Dziedziczenie i kompozycja Tworzenie nowych obiektów na bazie innych obiektów. Dziedziczenie to relacja jest, a kompozycja to relacja ma
Przykład class Car public virtual void MoveForward() Console.WriteLine( Do przodu ); class RacingCar : Car public override void MoveForward() Console.WriteLine( Szybka jazda do przodu ); public void StartOnBoardCamera() Console.WriteLine("Kamera włączona"); class FamilyCar : Car public override void MoveForward() Console.WriteLine("Wolno i bezpiecznie do przodu"); Technologie obiektowe
Obiekt klasy potomnej Car mycar; mycar = new RacingCar(); RacingCar myracingcar; MyRacingCar = new Car(); Car MoveForward() mycar.moveforward(); mycar.startonboardcamera(); //Nieprawidłowe RacingCar MoveForward() StartOnBoardCamera()
Wiązanie dynamiczne Car mycar; mycar = new RacingCar(); mycar.moveforward(); Czy zostanie wywołana metoda z klasy Car czy z klasy mycar? Środowisko musi podjąć ważną decyzję którą metode MoveForward uruchomić z klasy Car czy z klasy RacingCar?
Wiązanie dynamiczne Car mycar; Kompilator napotykając wiersz: mycar.moveforward(); Nie ma możliwości dowiedzieć się czy mycar będzie zawierała obiekt Car, RacingCar czy FamilyCar. Wiązanie dynamiczne, późne wiązanie faktyczna implementacja, którą ta nazwa reprezentuje jest określana dynamiczne podczas wykonywania programu.
Polimorfizm Polimorfizm oznacza zdolność do przyjmowania wielu postaci (wielopostaciowość) Stosowanie jednej zmiennej jako referencji do obiektów różnych klas i umożliwienie dzięki mechanizmowi wiązania dynamicznego, automatycznego wywołania metody zaimplementowanej w danym obiekcie. Wiązanie dynamiczne to po prostu fizyczna realizacja abstrakcyjnego pojęcia polimoforfizmu.
Metoda abstrakcyjna Metoda abstrakcyjna zawiera wyłącznie sam nagłówek bez implementacji Wymaga zapewnienia implementacji w klasach dziedziczących Kiedy klasa zawiera przynajmniej jedną metodę abstrakcyjną, to sama musi być również abstrakcyjna. Nie można utworzyć instancji klasy abstrakcyjnej. Słowo kluczowe abstract Metoda abstrakcyjna staje się niejawnie metodą wirtualną.
Klasy abstrakcyjne Nie możemy utworzyć instancji klasy abstrakcyjnej, jednak możemy zadeklarować zmienną jej typu referencyjnego. Nieabstrakcyjne klasy, których instancje można tworzyć bez przeszkód, nazywa się klasami konkretnymi. Akcesory get oraz set właściwości mogą być również deklarowane jako abstract
Kształty abstract class Shape public abstract void DrawYourself(); class Triangle : Shape public override void DrawYourself() Console.WriteLine(" * "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" ********* "); class Rectangle : Shape public override void DrawYourself() Console.WriteLine(" ********* "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" ********* "); class Circle : Shape public override void DrawYourself() Console.WriteLine(" *** "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" *** ");
Kształty cd. class Program static void Main(string[] args) Shape myshape; Random r = new Random(); List<Shape> shapes=new List<Shape>(); Technologie obiektowe double los; for (int i = 0; i < 3; i++) los=r.next(3); if (los == 0) shapes.add(new Triangle()); else if (los == 1) shapes.add(new Rectangle()); else shapes.add(new Circle()); foreach (Shape element in shapes) element.drawyourself(); Console.ReadKey(); * * * * * * * ********* *** * * * * * * *** ********* * * * * * * ********* * * * * * * * ********* * * * * * * * ********* ********* * * * * * * *********
Tożsamość klasy Shape myshape=new Rectangle(); Obiekt klasy Rectangle() traci część swojej tożsamości. Na poziomie kodu źródłowego MyShape nie jest w stanie nam wskazać referencji do odpowiedniej klasy. class Rectangle : Shape double width=20,height=20; public override void DrawYourself() Console.WriteLine(" ********* "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" * * "); Console.WriteLine(" ********* "); Console.WriteLine(myShape.Height+'' ''+myshape.width); Error 2 'ConsoleApplication8.Shape' does not contain a definition for 'height' and no extension method 'height' accepting a first argument of type 'ConsoleApplication8.Shape' could be found Technologie obiektowe
Operator is Operator is może sprawdzić, czy zmienna odnosi się do obiektu określonego typu. Wynikiem sprawdzenia jest true/false bool Console.WriteLine(myShape is Rectangle); Rectangle rect; if (myshape is Rectangle) rect = (Rectangle)myShape; Console.WriteLine(rect.width + " " + rect.height);
Rzutowanie Car mycar=new RacingCar(); Wszystkie elementy klasy, które można wywołać z Car można też wywołać z RacingCar. Ponieważ Car znajduje się wyżej w hierarchi dziedziczenia, takie przypisania wymaga rzutowania w górę Rectangle rect=(rectangle)myshape; Jeśli jesteśmy pewni, że myshape odnosi się do Rectangle!! Rzutowanie w dół wymaga operatora (<T>)
Rzutowanie Uwaga: myshape = new Circle(); Rectangle rect; rect = (Rectangle)myShape; Unable to cast object of type 'ConsoleApplication8.Circle' to type 'ConsoleApplication8.Rectangle'.
Operator as Operator as umożliwia kontrolowany proces rzutowania w dół. myshape = new Rectangle(); Rectangle rect= myshape as Rectangle; if(rect!=null) Console.WriteLine(rect.width); OK myshape = new Circle(); Rectangle rect= myshape as Rectangle; if(rect!=null) Console.WriteLine(rect.width); NULL
System.Object Biblioteka klas.net zawiera klasę o nazwie System.Object, z które ostatecznie wyprowadzane są wszystkie klasy Jeżeli tworzymy klasę bez określenie jej klasy bazowej, C# automatycznie ustawia klasę bazową jako System.Object. Hierarchia klas zawsze ma klasę stanowiącą najwyższe ogniwo w C# jest to zawsze System.Object
System.Object Każdy obiekt jest obiektem klasy System.Object foreach (Shape element in shapes) Console.WriteLine(element is System.Object); element.drawyourself(); Najczęściej wykorzystywaną metodą z klasy System.Object jest ToString() True, true, true foreach (Shape element in shapes) Console.WriteLine(element is System.Object); Console.WriteLine(element.GetType()); //element.drawyourself(); True ConsoleApplication8.Triangle True ConsoleApplication8.Triangle True ConsoleApplication8.Circle
Kształty cd. Klasa Shape, zawiera metodę DrawYourself zadeklarowaną jako abstract, która obliguje każdą klasę pochodzącą od Shape do zaimplementowania tej metody (z tą samą sygnaturą i typem zwracanym). Każda klasa dziedzicząca musi wypełnić kontrakt: Ja klasa pochodząca od Shape, przysięgam niniejszym implementować każdą metodę abstrakcyjną zawartą w Shape albo sama będę abstrakcyjna Klasa abstrakcyjna Shape nie oferuje swoim potomkom nic poza powyższym zobowiązaniem.
Klasa abstrakcyjna interfejs Konstrukcja języka programowania zwana interfejsem klasa abstrakcyjna, jedynie z funkcjami abstrakcyjnymi. Klasa może implementować interfejs. Wówczas przyrzeka implementować składowe funkcyjne interfejsu. Problem dynamicznego wiązania i polimorfizmu bez zmian. Interfejs oferuje to samo.
Klasa abstrakcyjna a interfejs Syntaktycznie i semantycznie klasy abstrakcyjne i interfejsy są spokrewnione. Interfejsy mogą zawierać jedynie funkcje abstrakcyjne, a klasy abstrakcyjne jeszcze składowe danych i normalne funkcje. Implementacja wielu interfejsów nie daje takich samych potencjalnych problemów, jak wielokrotne dziedziczenie, ponieważ zderzenia składowych danych i implementacji nie istnieją. Klasa może mieć co najwyżej jedną klasę bazową i implementować nieograniczoną liczbę interfejsów.
Interfejs interface IDrawable void DrawYourself(); class Triangle : IDrawable public void DrawYourself() Console.WriteLine(" TROJKAT "); class Rectangle : IDrawable public double width = 20, height = 20; public void DrawYourself() Console.WriteLine(" PROSTOKAT "); class Circle : IDrawable public void DrawYourself() Console.WriteLine(" KOLKO ");
Interfejs Interfejsy stosuje się, kiedy dla kilku klas potrzebne są wspólne nagłówki funkcji, których nie ma w żadnej wspólnej klasie przodka. Umożliwia to zastosowanie polimorfizmu w zbiorze klas, niezależnie od ich położenia i hierarchii.
Klasy abstrakcyjne - nie można stworzyć ich instancji - specjalny typ klas, gdzie można mieć funkcje bez implementacji - klasa może dziedziczyć tylko z 1 klasy (C#, Java) dotyczy to równie klas abstrakcyjnych - zapewnia domyśle zachowania dla części elementów, zmuszając programistów do zaimplementowania pozostałych - cel: zapewnienie że coś zostanie zaimplementowane - klasa może dziedziczyć po klasie abstrakcyjnej nie implementując wszyskich metod też klasa abstrakcyjna - tylko z klasy z zaimplementowanymi wszystkimi metodami może powstać obiekt Związek : JEST CZYMŚ np. student JEST Osobą, Pracownik JEST osobą
Interfejsy - nie można stworzyć obiektów - specjalny typ klas abstrakcyjnych, gdzie WSZYSTKIE elementy nie mają implementacji - pozwala na polimorfizm. - dostarcza kontrakt, aby zapewnić zachowanie - klasa która implementuje interfejs MUSI zawierać pełną implementację, w przeciwnym razie kompilator zwróci błą - relacja MOŻE ZROBIĆ Trójkąt MOŻE rysować (Triangle implements Idrawable).
Wstęp do modelowania obiektowego - Jeśli mamy szczęście już na początku prac nad projektem dysponujemy pełną wiedzą nt. Kształtu przyszłego systemu. - Reakcja łańcuchowa - Wprowadzenie nawet najmniejszej zmiany, wymagają bardzo dużych nakładów pracy
Symptomy złego projektu Sztywność - brak elastyczności - uniemożliwia wprowadzenie do systemu nawet najdrobniejszych zmian - projekt można uznać za sztywny, jeśli pojedyncza zmiana powoduje całą serię następujących po sobie zmian w modułach zależnych - Zadanie okazało się bardziej skomplikowane niż sądzilismy
Symptomy złego projektu Wrażliwość - tendencja do ulegania uszkodzeniom lub usterkom w wielu różnych miejscach wskutek wprowadzenia nawet najdrobniejszych zmian - często pojawiają się w obszarach na pozór nie związanych ze zmienianym fragmentem Programiści wiedzą że takie moduły wymagają przeprojektowania, ale nikt nie chce podjąć się tego trudnego zadania.
Symptomy złego projektu Nieelastyczność - System jest nieelastyczny, jeśli zawiera elementy, które choć teoretycznie mogłyby zostać wykorzystane w innych systemach nie mogą być oderwane od oryginalnego systemu Niedostosowanie do rzeczywistości - niedostosowanie oprogramowania - niedostosowanie środowiska (niefektywne)
Symptomy złego projektu Nadmierna złożoność - system zawiera elementy, które w danej chwili są zbędne - programiści, próbują przedwcześnie przewidywać potencjalne zmiany wymagań Niepotrzebne powtórzenia - copy & paste Nieprzejrzystość - kod jest niezrozumiały, trudny do odczytania - Kod który ewoluuje, zwykle staje się nieprzejrzysty -