# C# in the Nuthsell - Interfejsy, dziedziczenie ## Interfejsy Wyobraź sobie sytuację, w której jesteś w ciemnym pokoju z przyjacielem i atakują was zombie. Krzyczysz do kolegi: "Rzuć mi coś, czym mogę uderzyć zombie!". W ten sposób definiujesz, że przedmiot który jest Ci potrzebny, jest możliwy do rzucenia, możliwy do złapania (bo inaczej to by było bez sensu) i można nim uderzyć zombie. Zdecydowanie różni się to od klas i obiektów opisywanych wcześniej - w programowaniu coś takiego nazwalibyśmy właśnie `interfejsem`. ```csharp= interface ICharacterUsable { void Use(Character user); } ``` Powyżej przedstawiono przykład interfejsu. Każda klasa, która go zaimplementuje, musi dostarczyć także implementacji dla metody `void Use(Character user)` > W C# przyjęto, że nazwy interfejsów rozpoczynamy od **I** ### Implementacja interfejsu ```csharp= interface IWeapon { int DmgBonus { get; set; } } class Weapon : IWeapon { public int DmgBonus { get; set; } } ``` Na powyższym przykładzie klasa `Weapon` implementuje interfejs `IWeapon`. Oznacza to, że musi zaimplementować także wszystkie metody, które są w nim zdefiniowane. ### Słowo kluczowe `override` To słowo kluczowe oznacza, że chcemy w klasie dziedziczącej nadpisać metodę z klasy bazowej. ```csharp= class Potion : Item { public override string ToString() { return $"Potion restoring {HpRestored}hp and {ManaRestored} mana"; } } ``` ### `IEnumerable<T>` Jest to interfejs wskazujący, że można iterować po klasie, która go implementuje. Przykładem takich klas są wszystkie kolekcje (np. listy). ### Sprawdzenie, czy klasa implementuje dany interfejs. ```csharp= if (item is ICharacterUsable usable) { // ... } ``` Powyższy warunek jest równoznaczny z "Jeśli `item` implementuje interfejs `ICharacterUsable`". ## Inne elementy języka C# ### Switch - case Ta konstrukcja oznacza, że porównujemy wartość wyrażenia podanego jako argument dla `switch` do wszystkich wartości z `case`. Jeśli wartość będzie taka sama, to wykonujemy kod przypisany do danego `case`. Jeśli nie, sprawdzamy dalej. Jeśli żadna z opcji nie pasuje, to wykonany zostanie kod z opcji `default`, chyba że taki nie zostanie zdefiniowany. ```csharp= switch (choice) { case '1': SelectItem(); break; case '2': Hit(Enemies); break; default: DoNothing(); break; } ``` > Jeśli pomienięte zostaną `break` w case'ach, to zostanie wykonany kod z kolejnego case'a itd. (chyba, że wśród instrukcji wewnątrz był `return`) ### Tymczasowe połączenie list Poniższe instrukcje pozwalają na połączenie list Characters i Enemies, ale tylko do iteracji w pętli foreach. ```csharp= foreach (var entity in DataContext.Characters.Concat(DataContext.Enemies)) { } ``` ### Funkcja lokalna Jest to rodzaj funkcji zdefiniowany "wewnątrz kodu", np. wewnątrz innej funkcji. W tym obszarze możemy z niego dowolnie korzystać, ale jest on niedostępny dla niczego z zewnątrz. ```csharp= bool IsAnyCharacterAndEnemyAlive() => DataContext.Characters.Any(character => character.IsAlive) && DataContext.Enemies.Any(enemy => enemy.IsAlive); ``` > `Shift+Alt+>` pozwala na zaznaczanie tych samych elementów w pliku > `Shift+Alt+<` pozwala je odznaczać ###### tags: `.Net PG` `C#` `interfejsy` `dziedziczenie`