Седма задача
- Краен срок
- 26.05.2011 17:00
Срокът за предаване на решения е отминал
Интерфейси
Интерфейсите са задължителни в статични типизираните езици. Duck typing-а значително намалява нуждата от тях. Въпреки това, те не съвсем безполезни в динамичен език.
Условие
Дефинирайте метаклас interface
, който позволява дефинирането на интерфейс и може да
проверява дали даден клас го имплементира. Един интерфейс е имплементиран от клас,
ако класът има всички методи и аргументите съвпадат.
class stack(metaclass=interface):
def push(self, item):
"""Pushes the item on the stack"""
def pop(self):
"""Returns the last pushed item on the stack"""
@stack
class CoolStack:
def push(self, item):
...
def pop(self):
...
За всеки интерфейс важи следното:
- Представлява клас, чиито метаклас е
interface
. - В интерфейса може да има само публични (незапочващи с
_
). Ако са дефинирани други атрибути (методи, започващи с_
или не-методи), трябва да се поражда грешка. - Методите могат да имат docstring.
- Имплементацията на методите в интерфейсите няма значение.
- Бонус точки, ако при метод, с код различен от (pass или docstring), пораждате грешка.
- Ползвайки интерфейса като клас-декоратор указвате, че даден клас го имплементира
Един клас имплементира един интерфейс, когато има всички методи от интерфейса и за тях е вярно:
Един клас klass
имплементира интерфейс intf
:
- Имат едни и същи позиционни аргументи, в един и същи ред.
- За всеки метод
intf.method
имаklass.method
. - Ако
intf.method
взема позиционни аргументи,klass.method
трябва да взема същия брой позиционни аргументи и те трябва да имат същите имена. - Ако
intf.method
взема*args
, тоklass.method
трябва задължително да взема*args
. - Ако
intf.method
не взема*args
, тоklass.method
трябва задължително да не взема*args
. - Аналогично за
**kwargs
. -
intf.method
иklass.method
могат да имат различни анотации. - Ако
intf.method
има keyword-only аргументи, тоklass.method
трябва да има същите. Не е задължително да са дефинирани в същия ред.klass.method(self, *, a, b)
е валидна имплементация наintf.method(self, *, b, a)
.
И допълнително:
- Ако
klass.method
няма docstring, трябва да го взема отintf.method
. - Ако искаме от вас да пораждате грешка, пораждайте
AssertionError
Ако искате да минете за баш майстори, направете интерфейса да поражда грешка, ако някой от методите в него има имплементация различна от docstring или pass
.