# 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`