# Programowanie obiektowe w Pythonie 3

Rozdział 3, Kiedy obiekty są do siebie podobne

## Proste dziedziczenie

```python
>>> from typing import List
>>> class Contact:
...    all_contacts: List["Contact"] = []
...    def __init__(self, name: str, email: str) -> None:
...        self.name = name
...        self.email = email
...        Contact.all_contacts.append(self)
...    def __repr__(self) -> str:
...        return (
...            f"{self.__class__.__name__}("
...            f"{self.name!r}, {self.email!r}"
...            f")"
...       )
...
>>> c_1 = Contact("Darek", "darek@mojsajt.com.pl")
>>> c_2 = Contact("Staszek", "stach@mojsajt.com.pl")
>>> Contact.all_contacts
[Contact('Darek', 'darek@mojsajt.com.pl'), Contact('Staszek', 'stach@mojsajt.com.pl')]


>>> class Supplier(Contact):
...    def order(self, order: "Order") -> None:
...        print(
...            "W tym miejscu prawdziwy system wysłałby "
...            f"zamówienie '{order}' do '{self.name}'"
...        )
...


>>> c = Contact("Jaki Gość", "jakigosc@mojsajt.com.pl")
>>> s = Supplier("Jan Dostawca", "dostawca@mojsajt.com.pl")
>>> print(c.name, c.email, s.name, s.email)
Jaki Gość jakigosc@mojsajt.com.pl Jan Dostawca dostawca@mojsajt.com.pl


>>> from pprint import pprint
>>> pprint(c.all_contacts)
[Contact('Darek', 'darek@mojsajt.com.pl'),
 Contact('Staszek', 'stach@mojsajt.com.pl'),
 Contact('Jaki Gość', 'jakigosc@mojsajt.com.pl'),
 Supplier('Jan Dostawca', 'dostawca@mojsajt.com.pl')]

>>> c.order("Potrzebuję kombinerek")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Contact' object has no attribute 'order'
>>> s.order("Potrzebuję kombinerek")
W tym miejscu prawdziwy system wysłałby zamówienie 'Potrzebuję kombinerek' do 'Jan Dostawca'


```

### Rozszerzanie typów wbudowanych

```python
>>> [] == list()
True

```

```python

>>> CL_2 = list["Contact"]
>>> type(CL_2)
<class 'types.GenericAlias'>

```

### Przesłanianie i super

```python
>>> class Friend(Contact):
...     def __init__(self, name: str, email: str, phone: str) -> None:
...         self.name = name
...         self.email = email
...         self.phone = phone

```

## Wielokrotne dziedziczenie

### Problematyczny diament

## Polimorfizm

## Studium przypadku

```python

>>> from typing import Iterable
>>> class SumPow:
...     def __call__(self, sequence: Iterable[float], p: float=1.0) -> float:
...         return sum(x**p for x in sequence)
        
>>> sum_pow = SumPow()
>>> distances=[3.0, 1.0, 2.0, 3.0]
>>> sum_pow(distances)
9.0
>>> sum_pow(distances, 2)
23.0
>>> sum_pow([2.5, 2.5], 2) == 12.5
True

```
