diff --git a/.github/workflows/module1.yml b/.github/workflows/module1.yml index 675dc7f04..d9e96931b 100644 --- a/.github/workflows/module1.yml +++ b/.github/workflows/module1.yml @@ -12,7 +12,7 @@ jobs: working-directory: shm run: | chmod +x check.sh - sudo apt install -y pcregrep - ./check.sh CMakeLists.txt + # sudo apt install -y pcregrep + # ./check.sh CMakeLists.txt # In case of conflict do not remove above jobs. Just add your jobs below and remove this comment :) diff --git a/module1/09-operators.md b/module1/09-operators.md index 395ce6e97..527f92fe2 100644 --- a/module1/09-operators.md +++ b/module1/09-operators.md @@ -37,7 +37,7 @@ public: ```cpp int main() { - Person adam("Adam", 25) + Person adam("Adam", 25); ++adam; std::cout << adam.getAge() << '\n'; // prints 26 } @@ -58,7 +58,7 @@ T& T::operator +=(const T2& b); ```cpp Computer& Computer::operator+=(Memory amount) { - ramAmount_ += number; + ramAmount_ += amount; std::cout << "Ram memory extended\n"; return *this; } diff --git a/module1/13-project.md b/module1/13-project.md index 6fac23232..b573407c7 100644 --- a/module1/13-project.md +++ b/module1/13-project.md @@ -50,8 +50,8 @@ ___ * Każde dostarczone zadanie to 5 punktów * 15 punktów za dostarczenie wszystkich 8 zadań do 28.06.2021 (poniedziałek) do 23:59 -* brak punktów bonusowych za dostarczenie tylko części zadań przed 28.06. -* 8 punktów za pracę w grupie dla każdej osoby z grupy. +* brak punktów bonusowych za dostarczenie tylko części zadań przed 28.06 +* 8 punktów za pracę w grupie dla każdej osoby z grupy ___ diff --git a/module1/index.html b/module1/index.html index 2f89e7ddc..66cc43c2e 100644 --- a/module1/index.html +++ b/module1/index.html @@ -26,7 +26,7 @@

Programowanie obiektowe

Object-Oriented Programming

- Coders School + Coders School

Mateusz Adamski

Łukasz Ziobroń

diff --git a/module2/presentation_inheritance.md b/module2/01-inheritance.md similarity index 98% rename from module2/presentation_inheritance.md rename to module2/01-inheritance.md index 0baa7910d..75047c6a2 100644 --- a/module2/presentation_inheritance.md +++ b/module2/01-inheritance.md @@ -5,7 +5,7 @@ ## Dziedziczenie - Coders School + Coders School ___ @@ -275,6 +275,8 @@ protected: class Laptop : public Computer, public Screen { Keyboard keyboard_; +public: + void getUserInput(); }; class Tablet : public Computer, diff --git a/module2/presentation_virtual.md b/module2/02-virtual.md similarity index 68% rename from module2/presentation_virtual.md rename to module2/02-virtual.md index 44a01f5d6..e98971d0f 100644 --- a/module2/presentation_virtual.md +++ b/module2/02-virtual.md @@ -2,10 +2,10 @@ # Programowanie obiektowe -## Metody wirtualne, interfejsy, klasy abstrakcyjne +## Metody czysto wirtualne, interfejsy, klasy abstrakcyjne - Coders School + Coders School ___ @@ -16,9 +16,9 @@ ___ ```cpp class Bird { public: - size_t getWeight(); - size_t getHeight(); - size_t getName(); + size_t getWeight() const { return weight_; } + size_t getHeight() const { return height_; } + std::string getName() const { return name_; } // Pure virtual function without implementation virtual void eat() = 0; @@ -32,7 +32,7 @@ protected: ``` -Metody `eat()` oraz `sleep()` to tzw. metody czysto wirtualne. Świadczy o tym `= 0;`. Oznacza to, że nigdzie nie znajdziemy ich implementacji dla klasy `Bird`. Klasy które dziedziczą po `Bird` będą ją musiały zaimplementować same. +Metody `eat()` oraz `sleep()` to tzw. metody czysto wirtualne (ang. pure virtual functions). Świadczy o tym `= 0;`. Oznacza to, że nigdzie nie znajdziemy ich implementacji dla klasy `Bird`. Klasy które dziedziczą po `Bird` będą ją musiały zaimplementować same. Znaczenie słowa `virtual` na razie przemilczymy. Jedyne co trzeba na teraz wiedzieć, to aby metoda była czysto wirtualna `= 0;` to musi być przed nią słowo `virtual`. @@ -71,7 +71,9 @@ ___ ## Użycie interfejsów ```cpp -class Penguin : public Bird, public Swimmable { +class Penguin : public Bird, + public Swimmable, + public Soundable { public: // Override from Bird void eat() override; @@ -79,19 +81,18 @@ public: // Override from Swimmable void swim() override; + + // Override from Soundable + void makeSound() override; }; class Hummingbird : public Bird, - public Flyable, - public Soundable { + public Flyable { public: // Override from Bird void eat() override; void sleep() override; - // Override from Soundable - void makeSound() override; - // Override from Flyable void fly() override; }; @@ -164,50 +165,5 @@ ___ ## Słowo `virtual` i `override` -Co to za słowa? Co one robią? O tym za chwilę ;) +Co to za słowa? Co one robią? O tym w jednym z następnych wideo ;) - -___ - -## Q&A - -___ - -## Zadanie 1 - -Przekształć klasę `Cargo` w interfejs z 4 czysto wirtualnymi metodami. - -```cpp -virtual size_t getPrice() const = 0; -virtual std::string getName() const = 0; -virtual size_t getAmount() const = 0; -virtual size_t getBasePrice() const = 0; -``` - -___ - -## Zadanie 1 cd. - -Utwórz 3 pochodne klasy `Cargo`: - -* `Fruit` -* `Alcohol` -* `Item` - -Klasa `Fruit` powinna mieć dodatkową zmienną określającą czas do zepsucia oraz `operator--` który będzie odejmował ten czas o 1. -Metoda `getPrice()` powinna redukować cenę odpowiednio wraz z czasem psucia naszego owocu. - -Klasa `Alcohol` powinna mieć dodatkową zmienną określającą procentowy udział spirytusu. -Metoda `getPrice()` powinna być proporcjonalnie wyższa w zależności od mocy alkoholu. -Należy ustalić bazową cenę za spirytus 96%. - -Klasa `Item` powinna mieć dodatkową zmienną enum określającą rzadkość przedmiotu (common, rare, epic, legendary). -Metoda `getPrice()` powinna być adekwatnie wyliczana od poziomu rzadkości przedmiotu. - -___ - -## Zadanie 2 - -Wykorzystując wspólną klasę bazową `Cargo` spróbuj przechowywać wszystkie towary w jednym wektorze w klasie `Ship`. - -Dodaj funkcję `void load(std::shared_ptr cargo)`, która dodaje towar i (dla chętnych) `void unload(Cargo* cargo)`, która usuwa towar z obiektu klasy `Ship`. diff --git a/module2/03-tasks.md b/module2/03-tasks.md new file mode 100644 index 000000000..5ace32ea4 --- /dev/null +++ b/module2/03-tasks.md @@ -0,0 +1,50 @@ + + +# Programowanie obiektowe + +## Zadania + + + Coders School + + +___ + +## Zadanie 5 + +Przekształć klasę `Cargo` w interfejs z 4 czysto wirtualnymi metodami. + +```cpp +virtual size_t getPrice() const = 0; +virtual std::string getName() const = 0; +virtual size_t getAmount() const = 0; +virtual size_t getBasePrice() const = 0; +``` + +___ + +## Zadanie 5 cd. + +Utwórz 3 pochodne klasy `Cargo`: + +* `Fruit` +* `Alcohol` +* `Item` + +Klasa `Fruit` powinna mieć dodatkową zmienną określającą czas do zepsucia oraz `operator--` który będzie odejmował ten czas o 1. +Metoda `getPrice()` powinna redukować cenę odpowiednio wraz z czasem psucia naszego owocu. + +Klasa `Alcohol` powinna mieć dodatkową zmienną określającą procentowy udział spirytusu. +Metoda `getPrice()` powinna być proporcjonalnie wyższa w zależności od mocy alkoholu. +Należy ustalić bazową cenę za spirytus 96%. + +Klasa `Item` powinna mieć dodatkową zmienną enum określającą rzadkość przedmiotu (common, rare, epic, legendary). +Metoda `getPrice()` powinna być adekwatnie wyliczana od poziomu rzadkości przedmiotu. + +___ + +## Zadanie 6 + +Wykorzystując wspólną klasę bazową `Cargo` spróbuj przechowywać wszystkie towary w jednym wektorze w klasie `Ship`. + +Dodaj funkcję `void load(std::shared_ptr cargo)`, która dodaje towar i (dla chętnych) `void unload(Cargo* cargo)`, która usuwa towar z obiektu klasy `Ship`. diff --git a/module3/presentation_polymorphism.md b/module2/04-polymorphism.md similarity index 92% rename from module3/presentation_polymorphism.md rename to module2/04-polymorphism.md index 32a9b3088..8c1b6e9f5 100644 --- a/module3/presentation_polymorphism.md +++ b/module2/04-polymorphism.md @@ -5,7 +5,7 @@ ## Polimorfizm - Coders School + Coders School ___ @@ -92,7 +92,7 @@ public: class SomeClass : public Interface { public: - void doSth() override; // there should be an implementation in cpp file + void doSth() override; // there should be an implementation in the cpp file }; int main() { @@ -110,7 +110,7 @@ ___ `override` jest opcjonalne. Jeśli go nie podamy za sygnaturą funkcji klasy pochodnej to metoda z klasy bazowej i tak zostanie nadpisana. -Jego użycie jest jednak dobrą praktyką, bo dzięki niemu kompilator sprawdzi czy faktycznie przeciążamy metodą z klasy bazowej i jeśli nie, to program się nie skompiluje. +Jego użycie jest jednak dobrą praktyką, bo dzięki niemu kompilator sprawdzi, czy faktycznie nadpisujemy metodę z klasy bazowej i jeśli nie, to program się nie skompiluje. Bez `override` mogłaby zostać utworzona nowa metoda w klasie pochodnej, która nie nadpisuje niczego z klasy bazowej. @@ -230,7 +230,7 @@ ___ ```cpp class Doppler { public: - virtual sayHello() { std::cout << "I'm Doppler!"; } + virtual void sayHello() { std::cout << "I'm Doppler!"; } }; class Dwarf : public Doppler { @@ -347,21 +347,3 @@ int main() { std::unique_ptr child2 = std::make_unique(); } ``` - -___ - -## Q&A - -___ - -## Zadanie 3 - -Napisz klasę `DryFruit`, która dziedziczyć będzie po klasie `Fruit`. - -Klasa ta powinna nadpisywać metody `getPrice()`, `getName()` oraz `operator--`. - -`operator--` powinien odejmować zużycie raz na 10 wywołań. - -Metoda `getPrice()` powinna zwracać trzykrotnie większą wartość w porównaniu do ceny bazowej. - -Przetestuj wywołania polimorficzne oraz podziel się wnioskami. diff --git a/module2/05-tasks.md b/module2/05-tasks.md new file mode 100644 index 000000000..6711b6dbf --- /dev/null +++ b/module2/05-tasks.md @@ -0,0 +1,23 @@ + + +# Programowanie obiektowe + +## Zadania + + + Coders School + + +___ + +## Zadanie 7 + +Napisz klasę `DryFruit`, która dziedziczyć będzie po klasie `Fruit`. + +Klasa ta powinna nadpisywać metody `getPrice()`, `getName()` oraz `operator--`. + +`operator--` powinien odejmować zużycie raz na 10 wywołań. + +Metoda `getPrice()` powinna zwracać trzykrotnie większą wartość w porównaniu do ceny bazowej. + +Przetestuj wywołania polimorficzne oraz podziel się wnioskami w komentarzach :) diff --git a/module2/presentation_static.md b/module2/06-static.md similarity index 64% rename from module2/presentation_static.md rename to module2/06-static.md index 803b4f6fb..65fcd3190 100644 --- a/module2/presentation_static.md +++ b/module2/06-static.md @@ -2,26 +2,26 @@ # Programowanie obiektowe -## Zmienne i funkcje statyczne +## Pola i funkcje statyczne - Coders School + Coders School ___ -## "Zmienna lub stała klasy" +## Pola klasy Czasami chcielibyśmy przypisać jakąś stałą cechę do klasy. -Nie konkretnych obiektów, a klasy samej w sobie. +Nie konkretnych obiektów, a klasy samej w sobie, tak, aby była ona wspólna dla wszystkich obiektów tej klasy. Np. każdy obiekt klasy ma nazwę "Object". ```cpp class Object { public: - std::string GetName() const { return name_; } + std::string getName() const { return name_; } private: const std::string name_ = "Object"; @@ -44,28 +44,33 @@ Nawet jeżeli obiekt zajmowałby dużo miejsca w pamięci, a my chcielibyśmy ty ___ - + ## `static` Rozwiązaniem tej uciążliwości jest `static`. Co więcej, problem ten możemy rozwiązać na 2 sposoby. Nie musimy w ten sposób tworzyć specjalnie obiektu, aby dostać się do cechy klasy, jaką jest jej nazwa. ```cpp -class ObjectA { +class ClassA { public: - static std::string getName() { return "ObjectA"; } + static std::string getName() { return "ClassA"; } }; -class ObjectB { +class ClassB { public: static std::string name_; }; -std::string ObjectB::name_{"ObjectB"}; +std::string ClassB::name_{"ClassB"}; int main() { - std::cout << ObjectA::getName() << '\n'; - std::cout << ObjectB::name_ << '\n'; + std::cout << ClassA::getName() << '\n'; + std::cout << ClassB::name_ << '\n'; + + ClassA objA; + std::cout << objA.getName() << '\n'; + ClassB objB; + std::cout << objB.name_ << '\n'; return 0; } @@ -73,19 +78,3 @@ int main() { - -___ - -## Q&A - -___ - -## Zadanie 4 - -Przekształć klasę bazową `Coordinates`, tak aby miała funkcję statyczną - -```cpp -static size_t distance(const Coordinates& lhs, const Coordinates& rhs) -``` - -Funkcja ta powinna zwracać dystans pomiędzy dwoma pozycjami. diff --git a/module2/07-tasks.md b/module2/07-tasks.md new file mode 100644 index 000000000..e9026f135 --- /dev/null +++ b/module2/07-tasks.md @@ -0,0 +1,23 @@ + + +# Programowanie obiektowe + +## Zadania + + + Coders School + + +___ + +## Zadanie 8 + +Napisz/przekształć klasę `Coordinates`, która ma określać współrzędne na mapie. Powinna ona przyjmować w konstruktorze 2 parametry `positionX`, `positionY` oraz operator porównania. + +Ma ona posiadać funkcję statyczną `distance`: + +```cpp +static size_t distance(const Coordinates& lhs, const Coordinates& rhs) +``` + +Funkcja ta powinna zwracać dystans pomiędzy dwoma pozycjami. diff --git a/module2/08-recap.md b/module2/08-recap.md new file mode 100644 index 000000000..aaf40da9c --- /dev/null +++ b/module2/08-recap.md @@ -0,0 +1,25 @@ + + +# Programowanie obiektowe + +## Podsumowanie + + + Coders School + + +___ + +## Co pamiętasz z dzisiaj? + +### Zapisz w notatkach jak najwięcej haseł + + +1. dziedziczenie +2. wielodziedziczenie +3. funkcje czysto wirtualne +4. klasy abstrakcyjne +5. interfejsy +6. funkcje wirtualne +7. polimorfizm +8. pola i metody statyczne diff --git a/module2/09-homework.md b/module2/09-homework.md new file mode 100644 index 000000000..d5c6cfaca --- /dev/null +++ b/module2/09-homework.md @@ -0,0 +1,38 @@ + + +# Programowanie obiektowe + +## Praca domowa + + + Coders School + + +___ + +### Pre-work + +* Dowiedz się czym jest problem diamentowy +* Poczytaj o zasadach SOLID, dotyczących pisania dobrego kodu obiektowego +* Spróbujcie w grupie metodą Copy & Paste dorzucić system budowania cmake do projektu. W tym celu popatrzcie na dotychczasowe zadania domowe i plik CMakeLists.txt. + +___ + +### Post-work + +* Poczytaj o [Null object pattern](https://en.wikipedia.org/wiki/Null_object_pattern). Może się przydać w `university-db` +* `university-db` ciąg dalszy (14 XP) + +___ + +### `university-db` + +#### Wymagania (14 XP) + +* Przechowywanie rekordów pracowników uczelni o strukturze: imię, nazwisko, PESEL, płeć, adres, zarobki +* Wszystkie osoby niezależnie czy będą to pracownicy, czy studenci mają być trzymani w jednym kontenerze +* Wypełnianie bazy danych sztucznymi danymi (generowanie danych) +* Modyfikacja zarobków wyszukując osobę po numerze PESEL (problematyczne) +* Sortowanie po zarobkach (problematyczne) + +Natkniecie się tutaj na typowe problemy związane z projektowaniem kodu zorientowanego obiektowo. Pomyślcie wspólnie na Planningu lub podczas Daily jak je rozwiązać. diff --git a/module2/presentation_homework.md b/module2/10-project.md similarity index 67% rename from module2/presentation_homework.md rename to module2/10-project.md index 13c848d34..86db524e5 100644 --- a/module2/presentation_homework.md +++ b/module2/10-project.md @@ -2,7 +2,7 @@ # Programowanie obiektowe -## Podsumowanie +## Projekt SHM Coders School @@ -10,36 +10,11 @@ ___ -## Co pamiętasz z dzisiaj? - -### Napisz na czacie jak najwięcej haseł - - -1. dziedziczenie -2. wielodziedziczenie -3. funkcje wirtualne -4. funkcje czysto wirtualne -5. klasy abstrakcyjne -6. interfejsy -7. polimorfizm -8. pola i metody statyczne - -___ - -### Pre-work - -* Dowiedzcie się czym jest problem diamentowy -* Poczytajcie o zasadach SOLID, dotyczących pisania dobrego kodu obiektowego -* Lektura o wzorcach projektowych z przykładami w C++ - [refactoring.guru](https://refactoring.guru/design-patterns) -* Spróbujcie w grupie metodą Copy & Paste dorzucić system budowania cmake do projektu. W tym celu popatrzcie na dotychczasowe zadania domowe i plik CMakeLists.txt. - -___ - ## Projekt grupowy Wykorzystajcie kod napisany podczas zajęć. Możecie też skorzystać z kodu w katalogu [solutions](solutions) -Projekt grupowy - kontynuacja. Możecie zmienić grupę jeśli chcecie ;) +Kontynuujemy i rozwijamy dotychczasową aplikację 🙂 ___ @@ -54,11 +29,11 @@ ___ ### Punktacja -* 3 pierwsze zadania - 5 punktów +* zadania 1, 2, 3 - 5 punktów * zadania 4, 5, 6 - 8 punktów -* 20 punktów za dostarczenie wszystkich 6 zadań przed 05.07.2020 (niedziela) do 23:59 -* brak punktów bonusowych za dostarczenie tylko części zadań przed 05.07 -* 6 punktów za pracę w grupie dla każdej osoby z grupy. +* 15 punktów za dostarczenie wszystkich 6 zadań przed 18.07.2020 (niedziela) do 23:59 +* brak punktów bonusowych za dostarczenie tylko części zadań w terminie +* 6 punktów za pracę w grupie dla każdej osoby z grupy ___ diff --git a/module2/index.html b/module2/index.html index aaabe3623..2f358c691 100644 --- a/module2/index.html +++ b/module2/index.html @@ -23,10 +23,10 @@
-

OOP #2

-

Object-Oriented Programming #2

+

Programowanie obiektowe

+

Object-Oriented Programming

- Coders School + Coders School

Mateusz Adamski

Łukasz Ziobroń

@@ -39,38 +39,13 @@

Łukasz Ziobroń

1. dziedziczenie 2. wielodziedziczenie - 3. funkcje wirtualne 4. funkcje czysto wirtualne 5. klasy abstrakcyjne 6. interfejsy + 3. funkcje wirtualne 7. polimorfizm 8. pola i metody statyczne - Możliwe, że dzisiaj nie przerobimy wszystkiego. Będzie na kolejną lekcję :) - - - -
-
- -
-
-
@@ -89,23 +64,43 @@

Łukasz Ziobroń

You can change the port by using npm start -- --port=8001. --> -
+
+
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/module2/presentation_polymorphism.md b/module2/presentation_polymorphism.md deleted file mode 100644 index 5e46c6f19..000000000 --- a/module2/presentation_polymorphism.md +++ /dev/null @@ -1,367 +0,0 @@ - - -# Programowanie obiektowe - -## Polimorfizm - - - Coders School - - -___ - -## Słowo kluczowe `virtual` - -Jeżeli chcemy, aby przy używaniu wskaźników lub referencji na klasę bazową, jakaś metoda zachowywała się inaczej w zależności od prawdziwego typu obiektu, to należy ją oznaczyć słowem kluczowym `virtual`. Jest to tzw. funkcja wirtualna. - -___ - - -## Funkcja nie-wirtualna - -```cpp -#include - -struct Bird { - void sing() { std::cout << "tweet, tweet\n"; } -}; - -struct Sparrow : Bird { - void sing() { std::cout << "chirp, chirp\n"; } -}; - -int main() { - Sparrow sparrow; - Bird& bird = sparrow; - bird.sing(); - return 0; -} -``` - -Co pojawi się na ekranie? - - -`tweet, tweet` - - -___ - - -## Funkcja wirtualna - -```cpp -#include - -struct Bird { - virtual void sing() { std::cout << "tweet, tweet\n"; } -}; - -struct Sparrow : Bird { - void sing() { std::cout << "chirp, chirp\n"; } -}; - -int main() { - Sparrow sparrow; - Bird& bird = sparrow; - bird.sing(); - return 0; -} -``` - -Co pojawi się na ekranie? - - -`chirp, chirp` - - -[Sprawdź na ideone.com](https://ideone.com/yW43Tq) - - -___ - -## Słowo kluczowe `override` - -Jeżeli w klasie pochodnej **nadpisujemy** metodę wirtualną, czyli zmieniamy jej zachowanie, to należy dodać słowo `override`. - - -```cpp -class Interface { -public: - virtual void doSth() = 0; -}; - -class SomeClass : public Interface { -public: - void doSth() override; // there should be an implementation in cpp file -}; - -int main() { - // Interface interface; // Compilation error, Interface is pure virtual - SomeClass someClass; // OK - Interface* interface = &someClass; // OK, we hold a pointer -} -``` - - -___ - -### Mała uwaga - -`override` jest opcjonalne. Jeśli go nie podamy za sygnaturą funkcji klasy pochodnej to metoda z klasy bazowej i tak zostanie nadpisana. - - -Jego użycie jest jednak dobrą praktyką, bo dzięki niemu kompilator sprawdzi czy faktycznie nadpisujemy metodę z klasy bazowej i jeśli nie, to program się nie skompiluje. - - -Bez `override` mogłaby zostać utworzona nowa metoda w klasie pochodnej, która nie nadpisuje niczego z klasy bazowej. - - -Metody wirtualne **nadpisujemy**, nie przeciążamy. - - -___ - -## Nadpisywanie metod - `override` - -Wracając do przykładu o ptakach, klasy `Penguin`, `Hummingbird` oraz `Goose` to klasy pochodne, które dziedziczą po pewnych klasach bazowych jak `Bird`, `Flyable`, `Soundable`, `Swimmable` oraz nadpisują kilka ich metod jak: - -* void eat() override -* void sleep() override -* void makeSound() override -* void fly() override -* void swim() override - -Nadpisanie takich metod powoduje, że możemy zmienić ich implementacje. - - -___ - -## `override` - -```cpp -class Soundable { -public: - virtual void makeSound() = 0; -}; -``` - -```cpp -class Goose : public Soundable { -public: - void makeSound() override { std::cout << "Honk! Honk!"; } -}; -``` - -```cpp -class Hen : public Soundable { -public: - void makeSound() override { std::cout << "Cluck! Cluck!"; } -}; -``` - -```cpp -class Duck : public Soundable { -public: - void makeSound() override { std::cout << "Quack! Quack!"; } -}; -``` - -___ - -## Wspólna klasa bazowa - -Ponieważ wspólnym rodzicem wszystkich klas jest klasa `Soundable` możemy przechowywać w kontenerze wskaźniki typu `Soundable`. - -```cpp -std::vector> birds_; -``` - -### Jakie dane otrzymamy na wyjściu? - -```cpp -std::vector> birds_; -birds_.push_back(std::make_shared()); -birds_.push_back(std::make_shared()); -birds_.push_back(std::make_shared()); - -std::cout << birds_[0]->makeSound() << '\n'; -std::cout << birds_[1]->makeSound() << '\n'; -std::cout << birds_[2]->makeSound() << '\n'; -``` - - -___ - -## Polimorfizm - -Zjawisko, które właśnie zaobserwowaliśmy, nazywa się polimorfizmem. - -Polimorfizm pozwala funkcji przybrać różne formy (implementacje), tak jak na przykładzie. - - -Dlatego, jeżeli utworzymy kolejno obiekty `Goose`, `Hen` i `Duck` w zależności od obiektu zostanie wywołana jego wersja metody `makeSound`. - - -Polimorfizm włącza się, gdy mamy funkcje wirtualne i używamy wskaźników lub referencji na typ bazowy. - - -### Kto grał lub czytał Wiedźmina? - - -___ - -## Doppler :) - -W uniwersum wykreowanym przez naszego rodzimego pisarza Andrzeja Sapkowskiego, występuje pewna intrygująca i ciekawa rasa zwana Dopplerami. - - -Rasa ta potrafi przyjąć, postać różnych form życia, może stać się człowiekiem, elfem, krasnoludem. Zmienia w ten sposób swoje cechy jak głos, kolor włosów, a nawet ubranie! - - -Pomimo że rasa ta jest typu Doppler, potrafi w różnych okolicznościach podszywać się pod inne rasy jak elf, krasnolud czy człowiek. - - -Z punktu widzenia C++ nasz Doppler podlega zjawisku polimorfizmu. - - -___ - - -```cpp -class Doppler { -public: - virtual sayHello() { std::cout << "I'm Doppler!"; } -}; - -class Dwarf : public Doppler { -public: - virtual sayHello() { std::cout << "I'm Dwarf!"; } -}; - -class Elf : public Doppler { -public: - virtual sayHello() { std::cout << "I'm Elf!"; } -}; - -class Human : public Doppler { -public: - virtual sayHello() { std::cout << "I'm Human!"; } -}; - -int main() { - std::shared_ptr doppler1 = std::make_shared(); - std::shared_ptr doppler2 = std::make_shared(); - std::shared_ptr doppler3 = std::make_shared(); - - std::cout << doppler1->sayHello() << '\n'; - std::cout << doppler2->sayHello() << '\n'; - std::cout << doppler3->sayHello() << '\n'; -} -``` - - - -Jak widzimy, nasz Doppler może przyjąć różne formy i zachowywać się tak jak one. Wskaźnik jest typu Doppler, ale program dobrze wie, kiedy Doppler podszywa się pod człowieka, kiedy pod krasnoluda, a kiedy pod elfa. - -___ - - -## Nie-wirtualne destruktory - -Bardzo ważne w przypadku tworzenia metod wirtualnych i dziedziczenia jest tworzenie wirtualnych destruktorów. -Jeżeli korzystamy z dobroci polimorfizmu i nie oznaczymy destruktor jako `virtual` to destruktor ten nie zostanie wywołany. - -```cpp -#include -#include - -class Parent { -public: - Parent() { std::cout << "PARENT C'tor called\n"; } - ~Parent() { std::cout << "PARENT D'tor caller\n"; } -}; - -class Child : public Parent { -public: - Child() { std::cout << "CHILD C'tor called\n"; } - ~Child() { std::cout << "CHILD D'tor caller\n"; } -}; - -int main() { - Child child; // ok, object on stack, not a pointer -} -``` - -___ - -## Nie-wirtualne destruktory - problem - -```cpp -#include -#include -#include - -class Parent { -public: - Parent() { std::cout << "PARENT C'tor called\n"; } - ~Parent() { std::cout << "PARENT D'tor caller\n"; } -}; - -class Child : public Parent { -public: - Child() { std::cout << "CHILD C'tor called\n"; } - ~Child() { std::cout << "CHILD D'tor caller\n"; } -}; - -int main() { - // Problem - std::unique_ptr child = std::make_unique(); - - // But shared_ptr will cleanup properly - std::shared_ptr child2 = std::make_shared(); -} -``` - -___ - -## Wirtualny destruktor - -```cpp -#include -#include -#include - -class Parent { -public: - Parent() { std::cout << "PARENT C'tor called\n"; } - virtual ~Parent() { std::cout << "PARENT D'tor caller\n"; } -}; - -class Child : public Parent { -public: - Child() { std::cout << "CHILD C'tor called\n"; } - ~Child() override { std::cout << "CHILD D'tor caller\n"; } -}; - -int main() { - std::unique_ptr child2 = std::make_unique(); -} -``` - -___ - -## Q&A - -___ - -## Zadanie 3 - -Napisz klasę `DryFruit`, która dziedziczyć będzie po klasie `Fruit`. - -Klasa ta powinna nadpisywać metody `getPrice()`, `getName()` oraz `operator--`. - -`operator--` powinien odejmować zużycie raz na 10 wywołań. - -Metoda `getPrice()` powinna zwracać trzykrotnie większą wartość w porównaniu do ceny bazowej. - -Przetestuj wywołania polimorficzne oraz podziel się wnioskami. diff --git a/module2/presentation_solutions.md b/module2/presentation_solutions.md index 708e7969e..e090368cf 100644 --- a/module2/presentation_solutions.md +++ b/module2/presentation_solutions.md @@ -10,6 +10,12 @@ ___ +## Disclaimer + +W PDFie te rozwiązania mogą być częściowo ucięte. Przejdź do lekcji na platformie lub na GitHubie, aby zobaczyć je w całości. + +___ + ### Zadanie 1 Cargo.hpp @@ -247,11 +253,11 @@ Cargo* Player::getCargo(size_t index) const { } size_t Player::getAvailableSpace() const { - size_t total_cargo_amount = 0; + available_space_ = 0; for (const auto cargo : ship_->getCargos()) { - total_cargo_amount += cargo->getAmount(); + available_space_ += cargo->getAmount(); } - available_space_ = ship_->getCapacity() - total_cargo_amount; + return available_space_; } ``` diff --git a/module2/solutions/exercise2.cpp b/module2/solutions/exercise2.cpp deleted file mode 100644 index 2db682909..000000000 --- a/module2/solutions/exercise2.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -class Cargo; - -class Ship { -public: - void Load(std::unique_ptr cargo) { - if (auto match_cargo = FindMatchCargo(cargo.get())) { - *match_cargo += cargo->GetAmount(); - return; - } - cargo_.push_back(std::move(cargo)); - } - - void Unload(Cargo* cargo) { - RemoveFromStorage(cargo); - } - - Cargo* FindMatchCargo(Cargo* cargo) { - for (auto el : cargo_) { - if (el->GetName() == "Fruit") { - if (el->GetName() == cargo->GetName() && - el->GetBasePrice() == cargo->GetBasePrice() && - el->GetExpiryDate() == cargo->GetExpiryDate()) - return el.get(); - } else if (el->GetName() == "Alcohol") { - if (el->GetName() == cargo->GetName() && - el->GetBasePrice() == cargo->GetBasePrice() && - el->GetPercentage() == cargo->GetPercentage()) - return el.get(); - } else { - if (el->GetName() == cargo->GetName() && - el->GetBasePrice() == cargo->GetBasePrice() && - el->GetRarity() == cargo->GetRarity()) - return el.get(); - } - } - } - - void RemoveFromStorage(Cargo* cargo) { - cargo_.erase(std::find_if(std::begin(cargo_), std::end(cargo_), - [cargo](const auto& el) { - return *el == *cargo; - })); - } -}; diff --git a/module2/solutions/exercise1.cpp b/module2/solutions/exercise5.cpp similarity index 65% rename from module2/solutions/exercise1.cpp rename to module2/solutions/exercise5.cpp index a25ebf118..cc652dedc 100644 --- a/module2/solutions/exercise1.cpp +++ b/module2/solutions/exercise5.cpp @@ -6,10 +6,10 @@ class Cargo { Cargo(size_t amount, std::string name, size_t base_price); virtual ~Cargo() = default; - virtual size_t GetPrice() const = 0; - virtual std::string GetName() const = 0; - virtual size_t GetAmount() const = 0; - virtual size_t GetBasePrice() const = 0; + virtual size_t getPrice() const = 0; + virtual std::string getName() const = 0; + virtual size_t getAmount() const = 0; + virtual size_t getBasePrice() const = 0; virtual Cargo& operator+=(size_t amount) = 0; virtual Cargo& operator-=(size_t amount) = 0; @@ -25,15 +25,15 @@ class Fruit : public Cargo { ~Fruit() override; // override from Cargo - size_t GetPrice() const override { + size_t getPrice() const override { if (time_elapsed_ >= expiry_date_) return 0; return static_cast( base_price_ * ((float)(expiry_date_ - time_elapsed_)) / expiry_date_); } - std::string GetName() const override { return name_; } - size_t GetAmount() const override { return amount_; } - size_t GetBasePrice() const override { return base_price_; } + std::string getName() const override { return name_; } + size_t getAmount() const override { return amount_; } + size_t getBasePrice() const override { return base_price_; } Cargo& operator--() { --amount_; return *this; @@ -47,8 +47,8 @@ class Fruit : public Cargo { return *this; } - size_t GetTimeElapsed() const { return time_elapsed_; } - size_t GetExpiryDate() const { return expiry_date_; } + size_t getTimeElapsed() const { return time_elapsed_; } + size_t getExpiryDate() const { return expiry_date_; } private: size_t time_elapsed_{0}; @@ -61,10 +61,10 @@ class Alcohol : public Cargo { ~Alcohol() override = default; // override from Cargo - size_t GetPrice() const override { return base_price_ * percentage_ / 96; } - std::string GetName() const override { return name_; } - size_t GetAmount() const override { return amount_; } - size_t GetBasePrice() const override { return base_price_; } + size_t getPrice() const override { return base_price_ * percentage_ / 96; } + std::string getName() const override { return name_; } + size_t getAmount() const override { return amount_; } + size_t getBasePrice() const override { return base_price_; } Cargo& operator+=(size_t amount) { amount_ += amount; return *this; @@ -74,7 +74,7 @@ class Alcohol : public Cargo { return *this; } - size_t GetPercentage() const { return percentage_; } + size_t getPercentage() const { return percentage_; } private: size_t percentage_; @@ -91,10 +91,10 @@ class Item : public Cargo { ~Item() override = default; // override from Cargo - size_t GetPrice() const override { return base_price_ * static_cast(rarity_); } - std::string GetName() const override { return name_; } - size_t GetAmount() const override { return amount_; } - size_t GetBasePrice() const override { return base_price_; } + size_t getPrice() const override { return base_price_ * static_cast(rarity_); } + std::string getName() const override { return name_; } + size_t getAmount() const override { return amount_; } + size_t getBasePrice() const override { return base_price_; } Cargo& operator+=(size_t amount) { amount_ += amount; return *this; @@ -104,7 +104,7 @@ class Item : public Cargo { return *this; } - Rarity GetRarity() const { return rarity_; } + Rarity getRarity() const { return rarity_; } private: Rarity rarity_; diff --git a/module2/solutions/exercise6.cpp b/module2/solutions/exercise6.cpp new file mode 100644 index 000000000..7374f04ff --- /dev/null +++ b/module2/solutions/exercise6.cpp @@ -0,0 +1,47 @@ +#include +#include + +class Cargo; + +class Ship { +public: + void load(std::unique_ptr cargo) { + if (auto match_cargo = findMatchCargo(cargo.get())) { + *match_cargo += cargo->getAmount(); + return; + } + cargo_.push_back(std::move(cargo)); + } + + void unload(Cargo* cargo) { + removeFromStorage(cargo); + } + + Cargo* findMatchCargo(Cargo* cargo) { + for (auto el : cargo_) { + if (el->getName() == "Fruit") { + if (el->getName() == cargo->getName() && + el->getBasePrice() == cargo->getBasePrice() && + el->getExpiryDate() == cargo->getExpiryDate()) + return el.get(); + } else if (el->getName() == "Alcohol") { + if (el->getName() == cargo->getName() && + el->getBasePrice() == cargo->getBasePrice() && + el->getPercentage() == cargo->getPercentage()) + return el.get(); + } else { + if (el->getName() == cargo->getName() && + el->getBasePrice() == cargo->getBasePrice() && + el->getRarity() == cargo->getRarity()) + return el.get(); + } + } + } + + void removeFromStorage(Cargo* cargo) { + cargo_.erase(std::find_if(std::begin(cargo_), std::end(cargo_), + [cargo](const auto& el) { + return *el == *cargo; + })); + } +}; diff --git a/module2/solutions/exercise3.cpp b/module2/solutions/exercise7.cpp similarity index 83% rename from module2/solutions/exercise3.cpp rename to module2/solutions/exercise7.cpp index d64f85256..c4b1e74d0 100644 --- a/module2/solutions/exercise3.cpp +++ b/module2/solutions/exercise7.cpp @@ -4,8 +4,8 @@ class DryFruit : public Fruit { public: // override from Cargo - std::string GetName() const override { return "Dry Fruit"; } - size_t GetPrice() const override { + std::string getName() const override { return "Dry Fruit"; } + size_t getPrice() const override { if (time_elapsed_ >= expiry_date_) return 0; return static_cast( diff --git a/module2/solutions/exercise4.cpp b/module2/solutions/exercise8.cpp similarity index 89% rename from module2/solutions/exercise4.cpp rename to module2/solutions/exercise8.cpp index a31dbd455..0963db555 100644 --- a/module2/solutions/exercise4.cpp +++ b/module2/solutions/exercise8.cpp @@ -6,7 +6,7 @@ class Coordinates { Coordinates() = default; Coordinates(size_t pos_x, size_t pos_y) : pos_x_(pos_x), pos_y_(pos_y) {} - static size_t Distance(const Coordinates& lhs, const Coordinates& rhs) { + static size_t distance(const Coordinates& lhs, const Coordinates& rhs) { return std::sqrt(std::pow((int)lhs.pos_x_ - (int)rhs.pos_x_, 2) + std::pow((int)lhs.pos_y_ - (int)rhs.pos_y_, 2)); } bool operator==(const Coordinates& lhs) const { diff --git a/module3/index.html b/module3/index.html deleted file mode 100644 index 1712af944..000000000 --- a/module3/index.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - Object Oriented Programming - Coders School - - - - - - - - - - - - - -
-
-
-
- -

OOP #3

-

Object-Oriented Programming #3

- - Coders School - -

Mateusz Adamski

-

Łukasz Ziobroń

- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
-
-
-
- -

Coders School

- Coders School - -
-
-
- - - - - - - - - diff --git a/module3/presentation_homework.md b/module3/presentation_homework.md deleted file mode 100644 index 13c848d34..000000000 --- a/module3/presentation_homework.md +++ /dev/null @@ -1,148 +0,0 @@ - - -# Programowanie obiektowe - -## Podsumowanie - - - Coders School - - -___ - -## Co pamiętasz z dzisiaj? - -### Napisz na czacie jak najwięcej haseł - - -1. dziedziczenie -2. wielodziedziczenie -3. funkcje wirtualne -4. funkcje czysto wirtualne -5. klasy abstrakcyjne -6. interfejsy -7. polimorfizm -8. pola i metody statyczne - -___ - -### Pre-work - -* Dowiedzcie się czym jest problem diamentowy -* Poczytajcie o zasadach SOLID, dotyczących pisania dobrego kodu obiektowego -* Lektura o wzorcach projektowych z przykładami w C++ - [refactoring.guru](https://refactoring.guru/design-patterns) -* Spróbujcie w grupie metodą Copy & Paste dorzucić system budowania cmake do projektu. W tym celu popatrzcie na dotychczasowe zadania domowe i plik CMakeLists.txt. - -___ - -## Projekt grupowy - -Wykorzystajcie kod napisany podczas zajęć. Możecie też skorzystać z kodu w katalogu [solutions](solutions) - -Projekt grupowy - kontynuacja. Możecie zmienić grupę jeśli chcecie ;) - -___ - -## Organizacja prac - -* Jak wyglądało wasze daily? -* Czy Code Review nie jest zaniedbane? -* Czy współpraca idzie gładko? -* Zróbcie sobie retrospektywę :) - -___ - -### Punktacja - -* 3 pierwsze zadania - 5 punktów -* zadania 4, 5, 6 - 8 punktów -* 20 punktów za dostarczenie wszystkich 6 zadań przed 05.07.2020 (niedziela) do 23:59 -* brak punktów bonusowych za dostarczenie tylko części zadań przed 05.07 -* 6 punktów za pracę w grupie dla każdej osoby z grupy. - -___ - -## Zadanie 1 - -Napisz klasę `Store`, która będzie umożliwiała dokonywanie zakupów. Wykorzystaj poniższy enum i funkcje. - -```cpp -enum class Response {done, lack_of_money, lack_of_cargo, lack_of_space}; - -Response buy(Cargo* cargo, size_t amount, Player* player); -Response sell(Cargo* cargo, size_t amount, Player* player); -``` - -___ - -## Zadanie 2 - -W klasach `Alcohol`, `Fruit`, `Item` dopisz brakujące metody oraz ich implementacje. - -```cpp -// override from Cargo -size_t getPrice() const override; -std::string getName() const override { return name_; } -size_t getAmount() const override { return amount_; } -size_t getBasePrice() const override { return base_price_; } -Cargo& operator+=(size_t amount) override; -Cargo& operator-=(size_t amount) override; -bool operator==(Cargo& cargo) const override; -``` - -___ - -## Zadanie 3 - -Dopisz do klasy `Ship`, `Cargo` oraz `Store` metodę `nextDay()` - -* Klasa `Ship`: Metoda powinna odejmować po 1 sztuce monety za każdego członka załogi. -* Klasa `Cargo`: Metoda powinna powodować psucie się towarów. -* Klasa `Store`: Metoda powinna zmieniać ilość towaru w sklepach. - -___ - -## Zadanie 4 (dla ambitnych) - -Spróbuj napisać klasę `Time`, która będzie odpowiadać za zarządzanie czasem w grze. - -Klasa ta powinna informować inne klasy, takie jak `Cargo`, `Ship`, `Store` o upłynięciu każdego dnia. - -Poczytaj czym jest wzorzec projektowy [`Observer`](https://refactoring.guru/design-patterns/observer). - -___ - -## Zadanie 5 (dla ambitnych) - -Napisz zaprzyjaźniony operator wypisywania do strumienia - -```cpp -friend std::ostream& operator<<(std::ostream& out, const Store& store); -``` - -Ma on w przystępny sposób wypisywać towar, jaki znajduje się w danym sklepie. - -___ - -## Zadanie 6 (dla ambitnych) - -Napisz klasę `Game`, która zarządzać będzie całą rozgrywką. - -Dodaj jej jedną metodę publiczną `startGame()`. - -Finalnie plik main powinien wyglądać tak: - -```cpp -#include "Game.hpp" - -constexpr size_t start_money = 1'000; -constexpr size_t game_days = 100; -constexpr size_t final_goal = 2'000; - -int main() { - Game game(start_money, game_days, final_goal); - game.startGame(); - - return 0; -} -``` diff --git a/module3/presentation_solutions.md b/module3/presentation_solutions.md deleted file mode 100644 index 24c5503b1..000000000 --- a/module3/presentation_solutions.md +++ /dev/null @@ -1,267 +0,0 @@ - - -# Programowanie obiektowe - -## Przykładowe rozwiązania - - - Coders School - - -___ - -## Disclaimer - -W PDFie te rozwiązania mogą być częściowo ucięte. Przejdź do lekcji na platformie lub na GitHubie, aby zobaczyć je w całości. - -___ - -### Zadanie 1 - -Cargo.hpp - -```cpp -bool operator==(const Cargo& cargo) const; -``` - -Cargo.cpp - -```cpp -bool Cargo::operator==(const Cargo& cargo) const { - return Cargo.getBasePrice() == base_price_ && Cargo.getName() == name_; -} -``` - -___ - -### Zadanie 2 - -Cargo.hpp - -```cpp -std::string getName() const; -size_t getAmount() const; -size_t getBasePrice() const; -``` - -Cargo.cpp - -```cpp -std::string Cargo::getName() const { return name_; } -size_t Cargo::getAmount() const { return amount_; } -size_t Cargo::getBasePrice() const { return base_price_; } -``` - -___ - -### Zadanie 3 #1 - -Island.hpp - -```cpp -#include -#include - -#include "Store.hpp" - -class Time; - -// Class describes position of island and available store. -class Island { -public: - class Coordinates { - public: - Coordinates() = default; - Coordinates(size_t pos_x, size_t pos_y) - : pos_x_(pos_x), pos_y_(pos_y) {} - - bool operator==(const Coordinates& lhs) const { - return this->pos_x_ == lhs.pos_x_ && this->pos_y_ == lhs.pos_y_; - } - - private: - const size_t pos_x_{0}; - const size_t pos_y_{0}; - }; - - Island() {} - Island(size_t pos_x, size_t pos_y, Time* time); - Coordinates getCoordinates() const { return position_; } - Store* getStore() const { return store_.get(); } - -private: - std::unique_ptr store_; - Coordinates position_; -}; -``` - -___ - -### Zadanie 3 #2 - -Island.cpp - -```cpp -#include "GTime.hpp" -#include "Island.hpp" - -Island::Island(size_t pos_x, size_t pos_y, Time* time) - : position_(Coordinates(pos_x, pos_y)), - store_(std::make_unique(time)) { -} -``` - -___ - -## Zadanie 4/5/6 #1 - -Map.hpp - -```cpp -class Time; - -// Class responsible for map generation which will be used to travel. -class Map { -public: - Map(Time* time); - void travel(Island* destination); - Island* getIsland(const Island::Coordinates& coordinate); - Island* getCurrentPosition() const { return current_position_; } - friend std::ostream& operator<<(std::ostream& out, const Map& map); - -private: - Island* current_position_; - std::vector islands_; -}; -``` - -___ - -### Zadanie 4/5/6 #2 - -Map.cpp - -```cpp -constexpr size_t kIslandNum = 10; -constexpr size_t kWidth = 50; -constexpr size_t kHeight = 50; - -Map::Map(Time* time) { - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> widthGen(0, kWidth); - std::uniform_int_distribution<> heightGen(0, kHeight); - std::vector islands(kIslandNum); - std::vector> usedPositions; - - // Generate map - for (size_t i = 0; i < kIslandNum; ++i) { - while (true) { - size_t x = widthGen(gen); - size_t y = heightGen(gen); - if (std::find_if(begin(usedPositions), - end(usedPositions), - [x, y](const auto& pos) { - return pos.first == x && pos.second == y; - }) == std::end(usedPositions)) { - usedPositions.push_back({x, y}); - islands_.push_back(Island(x, y, time)); - break; - } - } - } - - current_position_ = &islands_.front(); -} - -Island* Map::getIsland(const Island::Coordinates& coordinate) { - auto island = std::find_if(std::begin(islands_), - std::end(islands_), - [&coordinate](const Island& island) { - return coordinate == island.GetCoordinates(); - }); - return island != std::end(islands_) ? &*island : nullptr; -} - -void Map::travel(Island* destination) { - current_position_ = destination; -} -``` - -___ - -### Zadanie7/8 #1 - -Player.hpp - -```cpp -#include - -#include "Cargo.hpp" -#include "Ship.hpp" - -class Time; - -// Class is responsible for every action made by player -class Player { -public: - Player(size_t money, Time* time); - virtual ~Player() = default; - - virtual size_t getAvailableSpace() const; - virtual size_t getMoney() const; - virtual size_t getSpeed() const; - virtual Cargo* getCargo(size_t index) const; - -private: - std::unique_ptr ship_; - size_t money_; - size_t available_space_; -}; - -``` - -___ - -### Zadanie 7/8 #2 - -Player.cpp - -```cpp -constexpr size_t kCapacity = 100; -constexpr size_t kCrew = 50; -constexpr size_t kSpeed = 10; -constexpr char kName[] = "BLACK WIDOW"; -constexpr size_t kId = 10; - -Player::Player(size_t money, Time* time) - : ship_(std::make_unique(kCapacity, kCrew, kSpeed, kName, kId, time, this)), - money_(money), - available_space_(kCapacity) { -} - -size_t Player::getMoney() const { - return money_; -} - -size_t Player::getSpeed() const { - return ship_->getSpeed(); -} - -Cargo* Player::getCargo(size_t index) const { - return ship_->getCargo(index); -} - -size_t Player::getAvailableSpace() const { - available_space_ = 0; - for (const auto cargo : ship_->getCargos()) { - available_space_ += cargo->getAmount(); - } - - return available_space_; -} -``` - -___ - -## Q&A diff --git a/module3/presentation_static.md b/module3/presentation_static.md deleted file mode 100644 index da4b1bb48..000000000 --- a/module3/presentation_static.md +++ /dev/null @@ -1,91 +0,0 @@ - - -# Programowanie obiektowe - -## Zmienne i funkcje statyczne - - - Coders School - - -___ - - -## "Zmienna lub stała klasy" - -Czasami chcielibyśmy przypisać jakąś stałą cechę do klasy. -Nie konkretnych obiektów, a klasy samej w sobie. -Np. każdy obiekt klasy ma nazwę "Object". - - -```cpp -class Object { -public: - std::string GetName() const { return name_; } - -private: - const std::string name_ = "Object"; -}; -``` - - -W celu otrzymania nazwy tego obiektu, musimy najpierw utworzyć obiekt, a następnie zawołać `getName()`. - - -```cpp -int main() { - Object obj; - std::cout << obj.getName() << '\n'; -} -``` - - -Nawet jeżeli obiekt zajmowałby dużo miejsca w pamięci a my chcielibyśmy tylko jego nazwę i tak musimy go utworzyć, ponieważ tylko na nim możemy zawołać metodę `getName()`. - - -___ - - -## `static` - -Rozwiązaniem tej uciążliwości jest `static`. Co więcej, problem ten możemy rozwiązać na 2 sposoby. Nie musimy w ten sposób tworzyć specjalnie obiektu, aby dostać się do cechy klasy, jaką jest jej nazwa. - -```cpp -class ObjectA { -public: - static std::string getName() { return "ObjectA"; } -}; - -class ObjectB { -public: - static std::string name_; -}; - -std::string ObjectB::name_{"ObjectB"}; - -int main() { - std::cout << ObjectA::getName() << '\n'; - std::cout << ObjectB::name_ << '\n'; - - return 0; -} -``` - - - - -___ - -## Q&A - -___ - -## Zadanie 4 - -Przekształć klasę bazową `Coordinates`, tak aby miała funkcję statyczną - -```cpp -static size_t distance(const Coordinates& lhs, const Coordinates& rhs) -``` - -Funkcja ta powinna zwracać dystans pomiędzy dwoma pozycjami. diff --git a/shm/CMakeLists.txt b/shm/CMakeLists.txt index e69de29bb..630014b94 100644 --- a/shm/CMakeLists.txt +++ b/shm/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.10) + +set(CMAKE_C_COMPILER "/usr/bin/gcc") +set(CMAKE_CXX_COMPILER "/usr/bin/g++") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# set the project name +project(SHM) + +# set executables +set(THIS_PROJECT_SRC_DIRECTORIES + source/Island.cpp + source/Fortune.cpp + source/Map.cpp + source/Game.cpp + source/Cargo.cpp + source/Player.cpp + source/Ship.cpp + source/Fruit.cpp + source/DryFruit.cpp + source/Alcohol.cpp + source/Item.cpp + source/Store.cpp + source/Time.cpp +) +set(THIS_PROJECT_TESTS_DIRECTORIES +) + +# set flags +set(THIS_PROJECT_FLAGS + -Wall + -Werror + #-Weffc++ + -Wextra + -pedantic + -Wconversion + -O3 +) + +# add all executables +add_executable(${PROJECT_NAME} + main.cpp + ${THIS_PROJECT_SRC_DIRECTORIES} +) + +# specify compile options for target +target_compile_options(${PROJECT_NAME} PRIVATE ${THIS_PROJECT_FLAGS}) + +# enable standard cpp17 +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) + +# link ncurses static lib +target_link_libraries(${PROJECT_NAME} ncurses) + diff --git a/shm/README.md b/shm/README.md index 7a5027430..b64be1d21 100644 --- a/shm/README.md +++ b/shm/README.md @@ -27,7 +27,7 @@ ___ ## Zadanie 4 -Napisz klasę `Map`, która będzie posiadała `std::vector` przechowujący wszystkie wyspy na mapie, oraz zmienną `Island* currentPosition_` określającą aktualną pozycję gracza na mapie. +Napisz klasę `Map`, która będzie posiadała `std::vector` przechowujący wszystkie wyspy na mapie, oraz zmienną `Island* currentPosition_` określającą aktualną pozycję gracza na mapie. ___ @@ -45,7 +45,7 @@ W klasie `Map` napisz funkcję `Island* getIsland(const Island::Coordinates& coordinate)` -Powinna ona przeszukać `std::vector` i zwrócić szukaną wyspę. +Powinna ona przeszukać `std::vector` i zwrócić szukaną wyspę. ___ diff --git a/shm/check.sh b/shm/check.sh index fd537a421..2451f829a 100644 --- a/shm/check.sh +++ b/shm/check.sh @@ -85,3 +85,5 @@ if [ $failed == 0 ]; then else echo -e ❗️❗️❗️ $RED $failed "CHECKS FAILED" ❗️❗️❗️ $DEFAULT fi + +exit $failed diff --git a/shm/main.cpp b/shm/main.cpp new file mode 100644 index 000000000..62877ab4d --- /dev/null +++ b/shm/main.cpp @@ -0,0 +1,12 @@ +#include "source/Game.hpp" + +constexpr size_t start_money = 1'000; +constexpr size_t game_days = 100; +constexpr size_t final_goal = 2'000; + +int main() { + Game game(start_money, game_days, final_goal); + game.startGame(); + + return 0; +} diff --git a/shm/source/Alcohol.cpp b/shm/source/Alcohol.cpp new file mode 100644 index 000000000..14df22415 --- /dev/null +++ b/shm/source/Alcohol.cpp @@ -0,0 +1,22 @@ +#include "Alcohol.hpp" + +Alcohol::Alcohol(const std::string& name, const size_t amount, const size_t basePrice, const size_t voltage): + Cargo(name, amount, basePrice), + voltage_(voltage) +{} + +size_t Alcohol::getPrice() const { + return static_cast(static_cast(getBasePrice()) * (static_cast(voltage_) / 96.)); +} + +std::string Alcohol::getName() const { + return "Alcohol: " + name_; +} + +size_t Alcohol::getAmount() const { + return amount_; +} + +size_t Alcohol::getBasePrice() const { + return basePrice_; +} diff --git a/shm/source/Alcohol.hpp b/shm/source/Alcohol.hpp new file mode 100644 index 000000000..06d041013 --- /dev/null +++ b/shm/source/Alcohol.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "Cargo.hpp" + +#include + +class Alcohol : public Cargo { + size_t voltage_; + +public: + Alcohol(const std::string& name, const size_t amount, const size_t basePrice, const size_t voltage); + + size_t getPrice() const override; + + std::string getName() const override; + + size_t getAmount() const override; + + size_t getBasePrice() const override; +}; diff --git a/shm/source/Cargo.cpp b/shm/source/Cargo.cpp new file mode 100644 index 000000000..4993fb2b0 --- /dev/null +++ b/shm/source/Cargo.cpp @@ -0,0 +1,23 @@ +#include "Cargo.hpp" + +Cargo::Cargo(const std::string& name, const size_t amount, const size_t basePrice): + name_(name), + amount_(amount), + basePrice_(basePrice) +{} + +bool Cargo::operator==(const Cargo& cargo) const { + return (name_ == cargo.getName() && + amount_ == cargo.getAmount() && + basePrice_ == cargo.getBasePrice()); +} + +Cargo& Cargo::operator+=(size_t amount) { + amount_ += amount; + return *this; +} + +Cargo& Cargo::operator-=(size_t amount) { + amount_ = (amount_ > amount)? amount_ - amount : 0; + return *this; +} diff --git a/shm/source/Cargo.hpp b/shm/source/Cargo.hpp new file mode 100644 index 000000000..cd128680a --- /dev/null +++ b/shm/source/Cargo.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "Observer.hpp" + +#include + +class Cargo : Observer { +protected: + std::string name_; + size_t amount_; + size_t basePrice_; + +public: + // Observer: + virtual void nextDay() override = 0; + + // Cargo Interface: + Cargo(const std::string& name, const size_t amount, const size_t basePrice); + + virtual size_t getPrice() const = 0; + + virtual std::string getName() const = 0; + + virtual size_t getAmount() const = 0; + + virtual size_t getBasePrice() const = 0; + + bool operator==(const Cargo& cargo) const; + + Cargo& operator+=(size_t amount); + + Cargo& operator-=(size_t amount); +}; diff --git a/shm/source/Delegate.hpp b/shm/source/Delegate.hpp new file mode 100644 index 000000000..fa22dae07 --- /dev/null +++ b/shm/source/Delegate.hpp @@ -0,0 +1,8 @@ +#pragma once + +class Delegate { +public: + // ~Delegate(); + + virtual void payCrew(size_t price) = 0; +}; diff --git a/shm/source/DryFruit.cpp b/shm/source/DryFruit.cpp new file mode 100644 index 000000000..67777ff88 --- /dev/null +++ b/shm/source/DryFruit.cpp @@ -0,0 +1,22 @@ +#include "DryFruit.hpp" + +DryFruit::DryFruit(const std::string& name, const size_t amount, const size_t basePrice): + Fruit(name, amount, basePrice), + freshnessModifier_(10) +{} + +DryFruit& DryFruit::operator--() { + if (--freshnessModifier_ <= 0) { + freshnessModifier_ = 10; + Fruit::operator--(); + } + return *this; +} + +size_t DryFruit::getPrice() const { + return Fruit::getPrice() * 3; +} + +std::string DryFruit::getName() const { + return "DryFruit: " + name_; +} diff --git a/shm/source/DryFruit.hpp b/shm/source/DryFruit.hpp new file mode 100644 index 000000000..06ec92d98 --- /dev/null +++ b/shm/source/DryFruit.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Fruit.hpp" + +#include + +class DryFruit : public Fruit { + size_t freshnessModifier_; + +public: + DryFruit(const std::string& name, const size_t amount, const size_t basePrice); + + DryFruit& operator--() override; + + size_t getPrice() const override; + + std::string getName() const override; +}; diff --git a/shm/source/Fortune.cpp b/shm/source/Fortune.cpp new file mode 100644 index 000000000..6376f62e4 --- /dev/null +++ b/shm/source/Fortune.cpp @@ -0,0 +1,32 @@ +#include "Fortune.hpp" + +std::random_device randomDevice; +std::mt19937 randomEngine(randomDevice()); + +int Fortune::getNumber(int first, int last) { + if (first > last) { + std::swap(first, last); + } + std::uniform_int_distribution distribution(first, last); + return distribution(randomEngine); +} + +std::vector Fortune::getNumbersEvenlyDistributed(int first, int last, const int n) { + if (n < 1) { + return {}; + } + if (first > last) { + std::swap(first, last); + } + std::vector result(n); + for (int i = 0; i < n; ++i) { + int localFirst = (last / n * i) + first; + int localLast = (last / n * (i + 1)) + first; + result.at(i) = (getNumber(localFirst, localLast)); + } + return result; +} + +void Fortune::shuffle(std::vector& vector) { + std::shuffle(vector.begin(), vector.end(), randomEngine); +} diff --git a/shm/source/Fortune.hpp b/shm/source/Fortune.hpp new file mode 100644 index 000000000..df5252ae6 --- /dev/null +++ b/shm/source/Fortune.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include + +namespace Fortune { + int getNumber(int first, int last); + std::vector getNumbersEvenlyDistributed(int first, int last, const int n); + void shuffle(std::vector& vector); +} \ No newline at end of file diff --git a/shm/source/Fruit.cpp b/shm/source/Fruit.cpp new file mode 100644 index 000000000..bd166c747 --- /dev/null +++ b/shm/source/Fruit.cpp @@ -0,0 +1,32 @@ +#include "Fruit.hpp" + +Fruit::Fruit(const std::string& name, const size_t amount, const size_t basePrice): + Cargo(name, amount, basePrice), + maxFreshness_(10), + freshness_(maxFreshness_) +{} + +Fruit& Fruit::operator--() { + freshness_ = (freshness_ > 0)? freshness_ - 1 : 0; + return *this; +} + +size_t Fruit::getPrice() const { + return static_cast(static_cast(getBasePrice()) * (freshness_ / maxFreshness_)); +} + +std::string Fruit::getName() const { + return "Fruit: " + name_; +} + +size_t Fruit::getAmount() const { + return amount_; +} + +size_t Fruit::getBasePrice() const { + return basePrice_; +} + +void Fruit::nextDay() { + operator--(); +} diff --git a/shm/source/Fruit.hpp b/shm/source/Fruit.hpp new file mode 100644 index 000000000..ec26c1e14 --- /dev/null +++ b/shm/source/Fruit.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "Cargo.hpp" + +#include + +class Fruit : public Cargo { + const double maxFreshness_; + double freshness_; + +public: + Fruit(const std::string& name, const size_t amount, const size_t basePrice); + + virtual Fruit& operator--(); + + virtual size_t getPrice() const override; + + virtual std::string getName() const override; + + size_t getAmount() const override; + + size_t getBasePrice() const override; + + void nextDay() override; +}; diff --git a/shm/source/Game.cpp b/shm/source/Game.cpp new file mode 100644 index 000000000..15182fdc9 --- /dev/null +++ b/shm/source/Game.cpp @@ -0,0 +1,100 @@ +#include "Game.hpp" +#include "Observer.hpp" + +Game::Game(const size_t startMoney, + const size_t gameDays, + const size_t finalGoal): + money_(startMoney), + days_(gameDays), + final_goal_(finalGoal), + current_day_(1), + map_(std::make_unique()), + time_(std::make_unique