Програмиране с Python: Въведение в обектно-ориентирания дизайн
Author: Стефан Кънев, Николай Бачийски и Димитър Димитров

# Въведение в обектно-ориентирания дизайн

### „ Програмиране с Python“, ФМИ

#### # TODO Стефан Кънев
# TODO Николай Бачийски
# TODO Димитър Димитров

#### 12.05.2008

# Abstract Data Types (ADT)

Обектно-ориентираното програмиране ни позволява да моделираме концепции от външния свят в структури, разбираеми за машината. Това се нарича създаване на абстрактни типове на данни.

# class Polynomial(object)

    class Polynomial(object):
        def __init__(self, *cfs): ...
        def order(self): ...
        ...

    a = Polynomial(1, 4, 2) # x^2 + 4x + 2
    print a[3], a[2], a[1], a[0] # 0 1 4 2
    print a.order() # 2
    b = Polynomial(1, 1, 4, 1) # x^3 + x^2 + 4x + 1
    c = b - a # x^3 - 1
    d = Polynomial(1, 0, 0, 1) # x^3 + 1
    e = c * d # x^6 - 1

# Състояние и функционалност

Всеки обект може да се разглежда като сбор от две неща:

- Състояние - данни, които представят концепцията по някакъв начин.
- Функционалност - операции, които могат да бъдат извършени с тази концепция

# Интерфейс и имплементация

Интерфейс:

`y = power(x, a)`

Имплементация:

`def power(x, a): return 1 if a == 0 else power(x, a - 1) * x`

    def power(x, a):
        if a == 0: return 1
        r = power(x, a/2)
        return x * x * (x if a % 2 else 1)

`def power(x, a): return reduce(lambda a, b: a * b, [x] * a)`

    def power(x, a):
        r = 1
        for _ in range(a): r *= x
        return x

`def power(x, a): return x ** a`

# Представяне

Има различни начини, по които може да представим абстрактната концепция в примитивите на езика.

    (1, 2, 3)                 -> x^2 + 2x + 3
    (3, 1)                    -> 3x + 1

    ((1, 2), (2, 1), (3, 0))  -> x^2 + 2x + 3
    ((1, 1), (2, 1), (1, 0))  -> 3x + 1

    {2: 1, 1: 2, 0: 3}        -> x^2 + 2x + 3
    {1: 3, 0: 1}              -> 3x + 1

# Инвариант на представянето

Обикновено има разлика между множеството от стойности, които структурата на представянето може да приеме и множеството от стойности, които имат смисъл. Последните се наричат инвариант на представянето (representation invariant)

Например ако моделирате интервал от цели числа, може да го представите вътрешно като наредена двойка `(лява граница, дясна граница)`. Съответно, `(2, 6)` е смислено представяне, но `(6, 2)` - не.

# Абстрактна функция

Функцията (в математически смисъл) съпоставяща инварианта на представянето на множеството от моделирани концепции се нарича абстрактна функция на този абстрактен тип.

# Мутатори и наблюдатели

Методите на един обект могат да се разделят на два вида:

- мутатори - методи, променящи представянето
- наблюдатели (obeserver-и) - методи,

# Mutable и immutable обекти

- Обекти, които нямат мутатори (чието състояние не може да се променя след инстанциране) се наричат immutable.
- В Python няколко от вградените типове са такива - `int`, `tuple`, `str`, `float`, `long`, `complex` и т.н.
- Immutable обектите имат по-малко сложност. Това е добра причина да ги предпочитате

# Design by Contract

За всеки метод се дефинира следното:

- Предусловие (precondition) - условие, което трябва да бъде изпълнено за да може клиентът да извика този метод
- Постусловие (postcondition) - условие, гарантирано да бъде изпълнено след приключването на метода
- Инвариант (invariant) - условие, което трябва да бъде изпълнено по време на изпълнение на метода

# Liskov's Substitution Principle

Клас Б може да наследи от клас А, само ако на всички места на които може да използвате инстанция на А може да използвате инстанция на Б.

# Liskov's Substitution Principle (2)

В термините на Design by Contract:

Б може да наследи А ако:

- Дефинира толкова или по-малко строги предусловия от А
- Дефинира толкова или по-строги постусловия от А
- Запазва инвариантите на А

# Още въпроси?

- Страница на курса - http://fmi.py-bg.net/
- Форуми на курса - http://fmi.py-bg.net/forums/