1 / 48

Luokkien väliset koostesuhteet

Luokkien väliset koostesuhteet. Yhteyssuhde eli assosiaatio on yhteys luokkien välillä. Assosiaation erikoismuoto on koostesuhde (aggregation). Tässä mallinnetaan kokonaisuus/osa –suhdetta. Koostesuhde piirretään viivana, jonka kokonaispuolella on ontto vinoneliö.

ervin
Download Presentation

Luokkien väliset koostesuhteet

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Luokkien väliset koostesuhteet • Yhteyssuhde eli assosiaatio on yhteys luokkien välillä. • Assosiaation erikoismuoto on koostesuhde (aggregation). • Tässä mallinnetaan kokonaisuus/osa –suhdetta. • Koostesuhde piirretään viivana, jonka kokonaispuolella on ontto vinoneliö. • Voidaan myös puhua ”has-a” –suhteesta tai ”is-part-of” -suhteesta. • Koostesuhde (aggregation) ei mitenkään liitä kokonaisuuden ja osan elinkaaria yhteen. • Esimerkki koostesuhteesta (löyhä koostesuhde) kuvassa 1. tMyn

  2. Mikkelin Purjehtijat Tämä luokka edustaa ”kokonaisuutta”. 1 Tämä luokka edustaa toisen osaa * Purjevene Kuva 1. Koosteyhteys (aggregation, löyhä kooste). tMyn

  3. Siinä tapauksessa, että koostesuhteeseen halutaan voimakas omistussuhde ja elinkaarien yhteneväisyys, puhutaan vahvasta koosteesta (composite aggregation, composition). • Tässä tapauksessa osakokonaisuus voi olla osana vain yhdessä vahvassa koosteessa kerrallaan. • Kokonaisuutta edustavan osuuden on hallittava osiensa elinkaaret. • Vahva koostesuhde piirretään viivana, jonka kokonaispuolella on täytetty vinoneliö. • Esimerkki vahvasta koostesuhteesta kuvassa 2. tMyn

  4. Windows- Ikkuna Tämä luokka edustaa ”kokonaisuutta”. 1 Tämä luokka edustaa toisen osaa – ja voi olla vain yhden kokonaisuuden osana. * Kehys Kuva 2. Vahva koosteyhteys (composite aggregation, composition). tMyn

  5. Käytännössä koostesuhde rakennetaan siten, että luokka sisältää jonkin toisen luokan ilmentymän tai osoitteen toiseen luokkaan (miksei myös viittauksen). • Otetaan ensiksi esimerkki löyhästä koostesuhteesta (aggregation). Nyt siis luokkarakenne on hoidettava niin, että osaolio voi/saa jäädä eloon, vaikka koosteolio ei enää olisikaan olemassa. • Tämä onnistuu, kun toteutetaan koosteluokka niin, että siinä on osoitinviittaus osaolioon. tMyn

  6. Kun koosteluokkaan (Laitos) luodaan alla olevassa esimerkissä olio, niin silloin viitataan osoitinmuuttujalla osaluokan (Opettaja) olioon. Osaolion tietojäsenistä ei siis luoda (esim. kopiointimuodostimella) omia ilmentymiä tähän koosteolioon. Yksittäinen opettajailmentymä on siis ”pelkästään” töissä jonkin aikaa laitoksella: tMyn

  7. ”osat” Kirjoitetaan luokkaan leikki- hajotin, jotta nähdään sen tulevan kutsutuksi oikeaan aikaan. #include "stdafx.h" #include <iostream> #include <string> using namespace System; using namespace std; class Opettaja { public: Opettaja(); ~Opettaja(); void AsetaOpettajanNimi(); void AsetaOpettajanOsoite(); void HaeOpettajanNimi(); void HaeOpettajanOsoite(); private: string m_opettajannimi; string m_opettajanosoite; }; tMyn

  8. Opettaja::Opettaja() { cout<<"Opettaja-luokan oletusmuodostin, olio "<<this<<endl; AsetaOpettajanNimi(); AsetaOpettajanOsoite(); } void Opettaja::AsetaOpettajanNimi() { cout<<"Anna opettajan nimi: "; getline(cin, m_opettajannimi); } void Opettaja::AsetaOpettajanOsoite() { cout<<"Anna opettajan osoite: "; getline(cin, m_opettajanosoite); } void Opettaja::HaeOpettajanNimi() { cout<<"Opettajan nimi on "<<m_opettajannimi<<endl; } tMyn

  9. ”kokonaisuus” void Opettaja::HaeOpettajanOsoite() { cout<<"Opettajan osoite on "<<m_opettajanosoite<<endl; } Opettaja::~Opettaja() { cout<<"Opettaja-luokan hajotin, olio "<<this<<endl; } class Laitos { public: Laitos(Opettaja* , string); ~Laitos(); void OsoitaOpettaja(Opettaja*); void AsetaLaitos(string); void HaeLaitoksenOpettajanNimi(); void HaeLaitoksenOpettajanOsoite(); void HaeLaitoksenNimi(); tMyn

  10. private: // Aggregaatti Opettaja* mp_opettaja; string m_laitoksennimi; }; Laitos::Laitos(Opettaja* opettajaolio, string laitoksennimi) { cout<<"Laitos-luokan param. muodostin, olio "<<this<<endl; OsoitaOpettaja(opettajaolio); AsetaLaitos(laitoksennimi); } void Laitos::OsoitaOpettaja(Opettaja* opettajaolio) { mp_opettaja=opettajaolio; } void Laitos::AsetaLaitos(string laitoksennimi) { m_laitoksennimi=laitoksennimi; } tMyn

  11. void Laitos::HaeLaitoksenOpettajanNimi() { mp_opettaja->HaeOpettajanNimi(); } void Laitos::HaeLaitoksenOpettajanOsoite() { mp_opettaja->HaeOpettajanOsoite(); } void Laitos::HaeLaitoksenNimi() { cout<<"Laitoksen nimi on "<<m_laitoksennimi<<endl; } Laitos::~Laitos() { cout<<"Laitos-luokan hajotin, olio "<<this<<endl; } tMyn

  12. Kerrotaan muodostimelle, että kysymyksessä on string-luokan objekti. Nyt ei eka-olio ole enää olemassa! int main(array<System::String ^> ^args) { Opettaja ope=Opettaja(); ope.HaeOpettajanNimi(); { Laitos eka(&ope, string("Tekniikka ja liikenne")); eka.HaeLaitoksenOpettajanNimi(); eka.HaeLaitoksenNimi(); } ope.HaeOpettajanNimi(); return 0; } tMyn

  13. Edellisessä esimerkissä voidaan oliot muuttaa muistinvarausluokaltaan dynaamisiksi – kaikki muu pysyisi ennallaan: tMyn

  14. int main(array<System::String ^> ^args) { Opettaja* ope=new Opettaja(); ope->HaeOpettajanNimi(); Laitos* eka=new Laitos(ope, string("Tekniikka ja liikenne")); eka->HaeLaitoksenOpettajanNimi(); eka->HaeLaitoksenNimi(); delete eka; ope->HaeOpettajanNimi(); delete ope; return 0; } tMyn

  15. Tehdään edelliseen esimerkkiin sellainen muutos, että nyt kummassakin luokassa tietojäsenten muistinvarausluokka on dynaaminen. Tässä tapauksessa hajottimetkin ovat tarpeellisia. • Kuvassa 3 tuosta seuraavasta esimerkistä on UML-kaavio. tMyn

  16. #include "stdafx.h" #include <iostream> #include <string> using namespace System; using namespace std; class Opettaja { public: Opettaja(); ~Opettaja(); void AsetaOpettajanNimi(); void AsetaOpettajanOsoite(); void HaeOpettajanNimi(); void HaeOpettajanOsoite(); private: string* mp_opettajannimi; string* mp_opettajanosoite; }; tMyn

  17. Opettaja::Opettaja() { cout<<"Opettaja-luokan oletusmuodostin, olio "<<this<<endl; mp_opettajannimi=new string; AsetaOpettajanNimi(); mp_opettajanosoite=new string; AsetaOpettajanOsoite(); } void Opettaja::AsetaOpettajanNimi() { cout<<"Anna opettajan nimi: "; getline(cin, *mp_opettajannimi); } void Opettaja::AsetaOpettajanOsoite() { cout<<"Anna opettajan osoite: "; getline(cin, *mp_opettajanosoite); } tMyn

  18. void Opettaja::HaeOpettajanNimi() { cout<<"Opettajan nimi on "<<*mp_opettajannimi<<endl; } void Opettaja::HaeOpettajanOsoite() { cout<<"Opettajan osoite on "<<*mp_opettajanosoite<<endl; } Opettaja::~Opettaja() { cout<<"Opettaja-luokan hajotin, olio "<<this<<endl; delete mp_opettajannimi; delete mp_opettajanosoite; } tMyn

  19. class Laitos { public: Laitos(Opettaja* , string); ~Laitos(); void OsoitaOpettaja(Opettaja*); void AsetaLaitos(string); void HaeLaitoksenOpettajanNimi(); void HaeLaitoksenOpettajanOsoite(); void HaeLaitoksenNimi(); private: // Aggregaatti Opettaja* mp_opettaja; string* mp_laitoksennimi; }; tMyn

  20. Laitos::Laitos(Opettaja* opettajaolio, string laitoksennimi) { cout<<"Laitos-luokan param. muodostin, olio "<<this<<endl; OsoitaOpettaja(opettajaolio); mp_laitoksennimi=new string; AsetaLaitos(laitoksennimi); } void Laitos::OsoitaOpettaja(Opettaja* opettajaolio) { mp_opettaja=opettajaolio; } void Laitos::AsetaLaitos(string laitoksennimi) { *mp_laitoksennimi=laitoksennimi; } void Laitos::HaeLaitoksenOpettajanNimi() { mp_opettaja->HaeOpettajanNimi(); } tMyn

  21. void Laitos::HaeLaitoksenOpettajanOsoite() { mp_opettaja->HaeOpettajanOsoite(); } void Laitos::HaeLaitoksenNimi() { cout<<"Laitoksen nimi on "<<*mp_laitoksennimi<<endl; } Laitos::~Laitos() { cout<<"Laitos-luokan hajotin, olio "<<this<<endl; delete mp_laitoksennimi; } tMyn

  22. int main(array<System::String ^> ^args) { Opettaja* ope=new Opettaja(); ope->HaeOpettajanNimi(); Laitos* eka=new Laitos(ope, string("Tekniikka ja liikenne")); eka->HaeLaitoksenOpettajanNimi(); eka->HaeLaitoksenOpettajanOsoite(); eka->HaeLaitoksenNimi(); delete eka; ope->HaeOpettajanNimi(); ope->HaeOpettajanOsoite(); delete ope; return 0; } tMyn

  23. tMyn

  24. Kuva 3. UML-kaavio edellisestä esimerkistä, aggregation. tMyn

  25. Seuraava esimerkki sisältää vahvan koosteyhteyden (composition). Nyt osaoliolla ja koosteoliolla on yhtenevä elinkaari. • Ratkaisu toimii helposti siten, että koosteluokassa on suora viittaus osaolioon. Tällöin osaolio syntyy automaattisesti koosteolion tilanvarauksen yhteydessä, ja osaolio häviää automaattisesti koosteolion tilanvapautuksen yhteydessä. Koosteolion on aina pakko sisältää osaolio. tMyn

  26. Sekä koosteluokka että osaolioiden luokat voivat sisältää parametrillisia muodostimia. • Yleensä koosteluokan muodostimelle välitetään parametreina kaikille muodostimille välitettävät tiedot. • Koosteluokan muodostimessa ohjataan parametrit edelleen osaolioiden luokkien muodostimelle. tMyn

  27. #include "stdafx.h" #include <iostream> #include <string> using namespace System; using namespace std; class Pvm { public: Pvm(int, int, int, int, int); ~Pvm(); void AsetaPaiva(int); void AsetaKuukausi(int); void AsetaVuosi(int); void AsetaTunti(int); void AsetaMinuutti(int); void HaePvm(); Otetaan leikkihajotin mukaan, jotta varmistutaan, että se tulisi kutsutuksi oikeassa paikassa. tMyn

  28. private: int m_paiva; int m_kuukausi; int m_vuosi; int m_tunti; int m_minuutti; }; Pvm::Pvm(int paiva, int kuukausi, int vuosi, int tunti, int minuutti) { cout<<"Pvm-luokan 5.param. muodostin, olio "<<this<<endl; AsetaPaiva(paiva); AsetaKuukausi(kuukausi); AsetaVuosi(vuosi); AsetaTunti(tunti); AsetaMinuutti(minuutti); } void Pvm::AsetaPaiva(int paiva) { m_paiva=paiva; } tMyn

  29. void Pvm::AsetaKuukausi(int kuuukausi) { m_kuukausi=kuuukausi; } void Pvm::AsetaVuosi(int vuosi) { m_vuosi=vuosi; } void Pvm::AsetaTunti(int tunti) { m_tunti=tunti; } void Pvm::AsetaMinuutti(int minuutti) { m_minuutti=minuutti; } tMyn

  30. Pvm::~Pvm() { cout<<"Pvm-luokan hajotin, olio "<<this<<endl; } void Pvm::HaePvm() { cout<<"Ajankohta on "<<m_paiva<<"."<<m_kuukausi<<".” <<m_vuosi<<" klo. "<<m_tunti<<"."<<m_minuutti<<endl; } tMyn

  31. Viiteparametrien käyttö ”säästää” yhden kopiointitapahtuman. class Palaveri { public: Palaveri(int, int, int, int, int, string&, string&); ~Palaveri(); void AsetaPaikka(string&); void AsetaAihe(string&); void HaeTiedot(); void HaeAjankohta(); private: Pvm m_ajankohta; string m_paikka; string m_aihe; }; tMyn

  32. Parametrit välitetään osaolioille kirjoittamalla muodostimen otsikkorivin jälkeen kaksoispisteen jälkeen ne osaoliot, joiden parametrillista muodostinta halutaan kutsuttavan. Kunkin koosteluokassa määritellyn osaolion nimen yhteyteen sulkeisiin kirjoitetaan parametrina välitettävien tietojen arvot. Välitettävien parametrien tyypit ja lukumäärä määräävät kutsuttavan muodostimen. Palaveri::Palaveri(int paiva, int kuukausi, int vuosi, int tunti, int minuutti, std::string& paikka, std::string& aihe) : m_ajankohta(paiva, kuukausi, vuosi, tunti, minuutti) { cout<<"Palaveri-luokan muodostin, olio "<<this<<endl; AsetaPaikka(paikka); AsetaAihe(aihe); } tMyn

  33. void Palaveri::AsetaPaikka(std::string& paikka) { m_paikka=paikka; } void Palaveri::AsetaAihe(std::string& aihe) { m_aihe=aihe; } tMyn

  34. void Palaveri::HaeTiedot() { m_ajankohta.HaePvm(); cout<<"Paikkana on: "<<m_paikka<<endl <<"Aiheena on: "<<m_aihe<<endl; } Palaveri::~Palaveri() { cout<<"Palaveri-luokan hajotin, olio "<<this<<endl; } void Palaveri::HaeAjankohta() { m_ajankohta.HaePvm(); } tMyn

  35. Kerrotaan muodostimelle, että kysymyksessä on string-luokan objekti. int main(array<System::String ^> ^args) { //Pvm joku=Pvm(3,9,2009,13,30); //joku.HaePvm(); //Palaveri eka(11, 3, 2009, 14, 45, string("Mikpoli MA307"), string("Neuvottelukunnan kriisipalaveri")); Palaveri* eka=new Palaveri(11, 3, 2009, 14, 45, string("Mikpoli MA307"), string("Neuvottelukunnan kriisipalaveri")); eka->HaeTiedot(); delete eka; //Palaveri eka=Palaveri(11, 3, 2009, 14, 45, string("Mikpoli MA307"), string("Neuvottelukunnan kriisipalaveri")); //eka.HaeTiedot(); return 0; } tMyn

  36. tMyn

  37. Edellisessä esimerkissä kummankin luokan tietojäseniä olisi voinut olla muistinvarausluokaltaan dynaamisia. Silloin kumpikin luokka tarvitsisi todellisen hajottimen, kts. seuraava esimerkki. • Kuvassa 4 tuosta seuraavasta esimerkistä on UML-kaavio. tMyn

  38. #include "stdafx.h" #include <iostream> #include <string> using namespace System; using namespace std; class Pvm { public: Pvm(int, int, int, int, int); ~Pvm(); void AsetaPaiva(int); void AsetaKuukausi(int); void AsetaVuosi(int); void AsetaTunti(int); void AsetaMinuutti(int); void HaePvm(); tMyn

  39. private: int* mp_paiva; int* mp_kuukausi; int* mp_vuosi; int* mp_tunti; int* mp_minuutti; }; Pvm::Pvm(int paiva, int kuukausi, int vuosi, int tunti, int minuutti) : mp_paiva(NULL), mp_kuukausi(NULL), mp_vuosi(NULL), mp_tunti(NULL), mp_minuutti(NULL) { cout<<"Pvm-luokan muodostin, olio "<<this<<endl; mp_paiva=new int; AsetaPaiva(paiva); On hyvä ajatus alustaa osoitinmuuttujat muodostimessa. tMyn

  40. mp_kuukausi=new int; AsetaKuukausi(kuukausi); mp_vuosi=new int; AsetaVuosi(vuosi); mp_tunti=new int; AsetaTunti(tunti); mp_minuutti=new int; AsetaMinuutti(minuutti); } void Pvm::AsetaPaiva(int paiva) { *mp_paiva = paiva; } void Pvm::AsetaKuukausi(int kuukausi) { *mp_kuukausi=kuukausi; } tMyn

  41. void Pvm::AsetaVuosi(int vuosi) { *mp_vuosi=vuosi; } void Pvm::AsetaTunti(int tunti) { *mp_tunti=tunti; } void Pvm::AsetaMinuutti(int minuutti) { *mp_minuutti=minuutti; } Pvm::~Pvm() { cout<<"Pvm-luokan hajotin, olio "<<this<<endl; delete mp_paiva; delete mp_kuukausi; delete mp_vuosi; delete mp_tunti; delete mp_minuutti; } tMyn

  42. Viiteparametrin käyttö ”säästää” yhden kopiointitapahtuman. void Pvm::HaePvm() { cout<<"Ajankohta on "<<*mp_paiva<<"."<<*mp_kuukausi<<".” <<*mp_vuosi<<" klo. "<<*mp_tunti<<"."<<*mp_minuutti<<endl; } class Palaveri { public: Palaveri(int, int, int, int, int, string&, string&); ~Palaveri(); void AsetaPaikka(string&); void AsetaAihe(string&); void HaeTiedot(); void HaeAjankohta(); private: Pvm m_ajankohta; string* mp_paikka; string* mp_aihe; }; tMyn

  43. Palaveri::Palaveri(int paiva, int kuukausi, int vuosi, int tunti, int minuutti, std::string& paikka, std::string& aihe) : m_ajankohta(paiva, kuukausi, vuosi, tunti, minuutti), mp_paikka(NULL), mp_aihe(NULL) { cout<<"Palaveri-luokan muodostin, olio "<<this<<endl; mp_paikka=new string; AsetaPaikka(paikka); mp_aihe=new string; AsetaAihe(aihe); } void Palaveri::AsetaPaikka(std::string& paikka) { *mp_paikka = paikka; } tMyn

  44. void Palaveri::AsetaAihe(std::string& aihe) { *mp_aihe = aihe; } Palaveri::~Palaveri() { cout<<"Palaveri-luokan hajotin, olio "<<this<<endl; delete mp_paikka; delete mp_aihe; } void Palaveri:: HaeTiedot() { m_ajankohta.HaePvm(); cout<<"Paikkana on: "<<*mp_paikka<<endl <<"Aiheena on: "<<*mp_aihe<<endl; } tMyn

  45. Kerrotaan muodostimelle, että kysymyksessä on string-luokan objekti. void Palaveri:: HaeAjankohta() { m_ajankohta.HaePvm(); } int main(array<System::String ^> ^args) { Palaveri* p_yksi = new Palaveri(9,3,2009,13,30, string("Mikpoli MA307"), string("Neuvottelukunnan kriisipalaveri")); p_yksi-> HaeTiedot(); delete p_yksi; return 0; } tMyn

  46. Yhtä hyvin olio voi olla muistinvarausluokaltaan automaattinen: tMyn

  47. int main(array<System::String ^> ^args) { Palaveri yksi=Palaveri(9,3,2009,13,30, string("Mikpoli MA307"), string("Neuvottelukunnan kriisipalaveri")); yksi.HaeTiedot(); return 0; } tMyn

  48. Kuva 4. UML-kaavio edellisestä esimerkistä, composition. tMyn

More Related