Notatki

Transkrypt

Notatki
Programowanie 2. Język C++. Wykład 15.
15.1
15.2
15.3
15.4
15.5
15.6
15.7
15.8
15.9
15.1
Programowanie obiektowe ...................................................................................................................... 1
Zasada ‘otwartości-zamkniętości’ ............................................................................................................ 2
Zasada ‘podstawiania liskowej’ ............................................................................................................... 5
Zasada ‘odwrotnej zaleŜności’ ............................................................................................................... 6
Zasada ‘rozdzielania interfejsów’............................................................................................................. 7
Trzy zasady spójności pakietów .............................................................................................................. 9
Zasady budowania relacji między pakietami .......................................................................................... 10
Zasada ‘ograniczania nadpisania interfejsów ........................................................................................ 11
Zasada Demeter ................................................................................................................................... 11
Programowanie obiektowe
Programowanie obiektowe (ang. object-oriented programming) technika programowania w której program
komputerowy jest tworzony jako zbiór typów (klasy) i instancji typów czyli obiektów.
Powodem powstania języków obiektowych i obiektowych technik programowania była rosnąca wielkość
programów, konieczność budowania duŜych, rozproszonych systemów komputerowych z róŜnych dziedzin Ŝycia.
Obiektowe techniki programowania spowodowały powstanie obiektowych techniki analizy i modelowania
rozproszonych systemów komputerowych i obiektowych baz danych, http://www.omg.org/
Obiekty są określone przez
• stan, czyli zdefiniowany i zainicjowane atrybuty obiektu,
• zachowanie, czyli metody które słuŜą do wykonywania operacji na atrybutach obiektu).
Istotą programowania obiektowego jest
• łączenie róŜnych typów danych z operacjami na tych typach w jeden abstrakcyjny typ (klasę),
• moŜliwość definiowania relacji między abstrakcyjnym typami danych w celu umoŜliwienia polimorfizmu
instancji abstrakcyjnych typów danych (obiektów),
• moŜliwość dynamicznej konwersji między abstrakcyjnym typami danych.
Języki zorientowane obiektowo:
• Simula 67, pierwszy język zorientowany obiektowo, stworzony przez Ole-Johan Dahl i Kristen Nygaard w
Norwegian Computing Center, http://www.edelweb.fr/Simula/
•
Smalltalk, język stworzony przez Alana Kay’a w Xerox Palo Alto Research Center.
•
Java, język opracowny przez James’a Gosling’a w Sun Microsystems w 1991.
‘The Java programming language is a general-purpose concurrent class-based object-oriented
programming language, specifically designed to have as few implementation dependencies as possible.’
The Java Language Specification, Third Edition, http://java.sun.com/docs/books/jls/
•
C++, językiem zaprojektowany przez Bjarne'a Stroustrup’a, jest obiektowym rozszerzeniem języka C.
Standard for the C++ Programming Language, ISO/IEC 14882:1998.
•
C#, językiem zbudowany w oparciu składnię języka C++.
ECMA-334 3rd Edition / June 2005 C# LanguageSpecification:
“C# is intended to be a simple, modern, general-purpose, object-oriented programming language”.
1
Programowanie 2. Język C++. Wykład 15.
15.2
Zasada ‘otwartości-zamkniętości’
Zasada otwartości-zamkniętości, (ang.) open-close principle.
KaŜda część systemu (funkcja, klasa, moduł) powinna być tak modelowana, aby moŜna było łatwo ją
funkcjonalnie rozszerzać (rozbudowywać) bez konieczności modyfikowania istniejącego kodu.
(ang.) A module should be open for extension but closed for modification.
Zasada OCP została sformułowana przez Bertrand'a Meyer'a w 1988, jest najwaŜniejszą zasadą zorientowanego
obiektowo projektowania (object oriented design).
Zasada OCP oznacza, Ŝe
Dodanie nowej funkcjonalności do istniejącego pakietu (modułu) nie powinno wiązać się z przebudową
pakietu a tylko z dopisaniem nowego komponentu.
open - do modelowanego komponentu powinno łatwo dodawać się nowe elementy (metody, atrybuty).
closed – rozbudowa modelowanego komponentu nie powinna wymagać modyfikacji istniejącego kodu.
Zasadę Open-Close realizuje się poprzez stosowanie elementów abstrakcyjnych języka, np. w języku C++
stosowanie klas abstrakcyjnych.
2
Programowanie 2. Język C++. Wykład 15.
Przykład 1. Program niezgodny z zasadą otwartości-zamkniętości.
#include <iostream>
using namespace std ;
enum TypFigury {okrag, kwadrat};
class FiguraGeometryczna
{
public:
TypFigury typ;
};
class Punkt { };
class Okrag
{
public:
TypFigury typ;
private:
double promienOkregu;
Punkt
srodekOkregu;
};
class Kwadrat
{
public:
TypFigury
private:
double
Punkt
};
typ;
dlugoscBokuKwadratu;
gornyLewyWierzcholek;
void RysujKwadrat(class Kwadrat*){ cout << "RysujKwadrat()" << endl;}
void RysujOkrag(class Okrag*){ cout << "RysujOkrag()" << endl;}
void RysujFigury(FiguraGeometryczna * list[], int n)
{
int i;
for (i=0; i<n; i++)
{
class FiguraGeometryczna* s = list[i];
switch (s->typ)
{
case kwadrat:
RysujKwadrat((class Kwadrat*)s);
break;
case okrag:
RysujOkrag((class Okrag*)s);
break;
}
}
}
3
Programowanie 2. Język C++. Wykład 15.
Program napisany zgodnie zasadą otwartości-zamkniętości’.
class FiguraGeometryczna // klasa abstrakyjna
{
public:
virtual void Rysuj() const = 0;
// metoda czysto wirtualna
};
class Kwadrat : public FiguraGeometryczna
{
public:
virtual void Rysuj() const { cout << "Rysuj kwadrat "<< endl;}
};
class Okrag : public FiguraGeometryczna
{
public:
virtual void Rysuj() const { cout << "Rysuj okrag "<< endl;}
};
void RysujFigureGeometryczna(Set<FiguraGeometryczna*>& list)
{
for (Iterator<FiguraGeometryczna*>i(list); i; i++)
(*i)->Rysuj();
}
4
Programowanie 2. Język C++. Wykład 15.
15.3
Zasada ‘podstawiania liskowej’
Zasada podstawiania liskowej, (ang.) the Liskov substitution principle.
Klasy główne (klasa bazowa) powinna dać się zastąpić klasami dziedzicznymi (klasami pochodnymi).
(ang.) Subclasses should be substitutable for their base classes.
Zasada sformułowana w 1996 przez Barbarę Liskov w pracach dotyczących teorii abstrakcyjnych typów danych.
Zasadę moŜna równieŜ sformułować następująco:
funkcja której argumentem jest wskaźnik lub referencja do obiektu klasy bazowej powinna równieŜ akceptować
obiekty z klas pochodnych.
B. Meyer, Design by Contract, Technical Report TR-EI-12/CO, Interactive Software Engineering Inc., 1986.
D. Mandrioli, B. Meyer, eds., Design by Contract, in Advances in Object-Oriented Software Engineering,
Prentice Hall, 1991.
Przykład. Obiekty typu B, (typ B jest typem pochodnym dla A) mogą zastępować obiekty typu A.
#include<iostream>
using namespace std;
class A {
public:
virtual void metoda( A & ra, int i){
cout << "metoda() w A" << endl;
ra.xa=i;
}
private:
int xa;
};
class B :public A {
public:
void metoda( B & rb, int i){
cout << "metoda() w B" <<
rb.xb=i;
}
private:
int xb;
};
endl;
void main() {
A a;
B b;
a.metoda(b,10);
b.A::metoda(a,100);
}
5
Programowanie 2. Język C++. Wykład 15.
15.4
Zasada ‘odwrotnej zaleŜności’
Zasada odwrotnej zaleŜności, (ang.) dependency inversion principle.
Relacje między klasami naleŜy tak modelować aby zaleŜności były od elementów abstrakcyjnych, nie od
elementów konkretnych.
(ang.) Depend upon Abstractions. Do not depend upon concretions.
Przy modelowaniu relacji między klasami klasy główne (bazowe) powinny być klasami abstrakcyjnymi lub
interfejsami.
NaleŜy unikać zaleŜności od konkretnych funkcji lub klas.
Przykład. Zastowanie zasady ‘odwrotnej zaleŜności’.
class A {
public:
virtual void metoda() { cout << "metoda() w A " << endl; }
};
class B : public A {
public:
void metoda() { cout << "metoda() w B " << endl; }
};
void main( ) {
B b;
b.metoda();
A a;
a.metoda();
}
Prawidłowo określona zaleŜność między klasami.
class Abs {
public:
virtual void metoda() const = 0;
};
class A : public Abs {
public:
void metoda() { cout << "metoda() w A " << endl; }
};
class B : public Abs {
public:
void metoda() { cout << "metoda() w B " << endl; }
};
void main( ) {
B b;
b.metoda();
A a;
a.metoda();
}
6
Programowanie 2. Język C++. Wykład 15.
15.5
Zasada ‘rozdzielania interfejsów’
Zasada rozdzielania interfejsów, (ang.) interface segregation principle.
Lepiej mieć kilka interfejsów o konkretnej funkcjonalności niŜ jeden interfejs uniwersalny.
(ang.) Many client specific interfaces are better than one general purpose interface.
W języku C++ interejs jest klasą zawierającą tylko publiczne metody. Typową implementacją interfejsu jest
deklaracja klasy abstrakcyjnej, która zawiera tylko publiczne, czysto wirtualne metody.
Język C++/ CLI. Interejs jest klasą deklarowaną za pomocą modyfikatora interface.
• Klasa która dziedziczy od intefejsu (od klasy typu interface) musi implementować wszystkie elementy
interfejsu.
• Elementy interfejsu są tylko deklaracjmi (są elementami wirtualnymi).
• Interfejsy mogą między sobą być w relacji dziedziczenia.
• Domyślny typ dostępu w interfejsie jest public, i nie moŜe być zmieniony.
W jęzku UML interfejs definiowany jest jako nazwany zbiór operacji, charakteryzujący zachowanie się elementu
modelowanego systemu (specyfikacja UML 2.0 ).
Przykład. Deklaracja klasy typu interfejs w języku C++/ CLI.
public interface class A {
};
#include "stdafx.h"
#include <iostream>
using namespace std;
interface class IA {
void meoda1(int val);
void meoda2(double val);
};
ref class A: IA {
public:
virtual void meoda1(int val){}
// błąd, brak implementacji meoda2()
// virtual void meoda2(double val){}
};
void
main(){ }
7
Programowanie 2. Język C++. Wykład 15.
Przykład. Zastosowanie zasady ‘rozdzielania interfejsów’.
#include "stdafx.h"
#include <iostream>
using namespace std;
interface class IOtworz {
void otworz();
void zamknij();
};
interface class IUruchom {
void uruchom();
void wylacz();
};
ref class Samochod: IOtworz, IUruchom {
public:
virtual void otworz(){}
virtual void zamknij(){}
virtual void uruchom(){}
virtual void wylacz(){}
};
ref class Motocykl: IUruchom {public:
virtual void uruchom(){}
virtual void wylacz(){}
};
void
main(){ }
8
Programowanie 2. Język C++. Wykład 15.
15.6
Trzy zasady spójności pakietów
Trzy zasady spójności pakietów, (ang.) package cohesion principles.
Zasada 1. Zasada wielokrotnego uŜycia w kolejnych wersjach systemu, (ang.) Release reuse equivalency
principle.
Klasy podlegające wielokrotnemu uŜyciu powinny być umieszczane w jednym pakiecie.
(ang.) The granule of reuse is the granule of release.
Jednym z kryteriów grupowania klas w pakiet jest ich wielokrotne uŜycie (reuse).
Pakiet stanowi pewną zamkniętą cześć modelowanego systemu, dlatego jest równowaŜność między
wielokrotnym uŜyciem kodu (wielokrotnym uŜyciem klas) a wielokrotnym uŜyciem pakietu (części systemu).
Zasada 2. Powszechna zasada zamkniętości, (ang.) common closure principle.
Modyfikacja klasy w pakiecie nie powinna powodować konieczności modyfikacji klasy w innym pakiecie.
Zbiór klas w którym modyfikacja jednej klasy powoduje modyfikacje innej naleŜy grupować w jeden pakiet.
(ang.) Classes that change together, belong together.
Zasada 3. Zasada wielokrotnego uŜycia, (ang.) common reuse principle.
Klasy które nie są razem wielokrotnie wykorzystywane nie powinny być w jednym pakiecie,
(ang.) classes that aren't reused together should not be grouped together.
9
Programowanie 2. Język C++. Wykład 15.
15.7
Zasady budowania relacji między pakietami
Trzy zasady budowania relacji między pakietami, (ang.) package coupling principles.
Zasada 1. Zasada acyklicznej zaleŜności, (ang.) acyclic dependencies principle.
ZaleŜność między pakietami nie powinny tworzyć cykli.
(ang.) The dependencies betwen packages must not form cycles.
Zasada oznacza, Ŝe naleŜy budować programy złoŜone z niezaleŜnych pakietów, komponetów.
Zmiana kodu w jednym pakietów nie powinna wymuszać zmian w innych pakietach.
Zasada 2. Zasada stabilnej zaleŜności, (ang.) stable dependencies principle.
Przy modelowaniu naleŜy wybierać najbardziej stabilne zaleŜności.
(ang.) Depend in the direction of stability.
Stabilność pakietu jest miarą prawdopodobieństwa, Ŝe pakiet będzie musiał być modyfikowany.
Zasada oznacza, Ŝe zaleŜności między pakietami naleŜy modelować biorąc pod uwagę ich stabilność w relacji z
innymi pakietami.
Zasada 3. Zasada stabilności pakietów, (ang.) stable abstractions principle.
Stabilne pakiety powinny być pakietami abstrakcyjnymi.
(ang.) Stable packages should be abstract packages.
10
Programowanie 2. Język C++. Wykład 15.
15.8
Zasada ‘ograniczania nadpisania interfejsów
Zasada ograniczania nadpisania interfejsów, (ang.) narrow inheritance interface.
NaleŜy minimalizować liczbę metod abstrakcyjnych (czysto wirtualnych) dziedziczonych przez klasę
pochodną.
Zasada ograniczania interfejsów, (ang.) narrow inheritance interface - related heuristic
NaleŜy ograniczać (minimalizować) liczbę interfejsów w klasie.
(ang.) Minimize the public interface of a class.
15.9
Zasada Demeter
Zasada Demeter dla metod:
•
Metoda powinna wywoływać metody ze swojej klasy bezpośrednio.
•
Metoda powinna wywoływać metody ze swojego obszaru bezpośrednio (nie z podobszaru).
•
JeŜeli matoda wywoływana jest z parametrem, to moŜe zawierać wywoływania metod wykorzystujacych
ten parametr.
•
JeŜeli metoda tworzy lokalny obiekt, to moze zawierać wywołania metod tego obiektu.
•
Metody nie powinny wywoływać obiektów globalnych, ale mogą je przekazywać jako parametry.
11

Podobne dokumenty