Кроме того, другое решение гарантирует, что ваши элементы управления создаются в потоке пользовательского интерфейса, а не потоком рабочего потока, например.
Существуют некоторые случаи, где интерфейсы могут быть очень удобными. Скрученный делает довольно широкое применение из интерфейсы Zope , и в проекте я работал над интерфейсами Zope, работавшими действительно хорошо. Черты Enthought недавно упаковали добавленный интерфейсы , но у меня нет опыта с ними.
Остерегаются злоупотребления, хотя - утиный ввод и протоколы являются фундаментальным аспектом Python, только используйте интерфейсы, если они абсолютно необходимы.
Я не уверен, какова точка этого. Интерфейсы (этой формы, так или иначе) должны в основном работать вокруг отсутствия множественного наследования. Но Python имеет MI, итак, почему не только делают абстрактный класс?
class Something(object):
def some_method(self):
raise NotImplementedError()
def some_other_method(self, some_argument):
raise NotImplementedError()
В Python 2.6 и позже, можно использовать абстрактные базовые классы вместо этого. Они полезны, потому что можно затем протестировать, чтобы видеть, реализует ли что-то данную ABC при помощи "isinstance". Как обычно, в Python, понятие так строго не осуществляется, как это было бы на строгом языке, но это удобно. Кроме того, существуют хорошие идиоматические способы объявить, что абстрактные методы с декораторами - видят ссылку выше для примеров.
pythonic путь к тому, "Попросите прощение, а не получите разрешение". Интерфейсы весь о получении разрешения выполнить некоторую операцию на объекте. Python предпочитает это:
def quacker(duck):
try:
duck.quack():
except AttributeError:
raise ThisAintADuckException
Я не думаю, что интерфейсы добавили бы что-либо к среде кода.
Foo
и имеют метод bar()
, и он не делает, он бросит AttributeError
. Кажется довольно ненужным мне - когда я пишу классы как этот, я обычно просто делаю базовый класс (Ваш ISomething
) без методов и упоминания в фактической документации, которую подклассы методов, как предполагается, переопределяют.
Можно создать интерфейс на динамически типизированном языке, но нет никакого осуществления интерфейса во время компиляции. Компилятор статически типизированного языка предупредит Вас, если Вы забудете реализовывать (или опечатка!) метод интерфейса. Так как Вы не получаете такой справки на динамически типизированном языке, Ваше объявление интерфейса служит только в качестве документации. (Который является не обязательно плохо, это просто, что Ваше объявление интерфейса не обеспечивает преимущества во время выполнения по сравнению с записью комментариев.)
Я собираюсь сделать что-то похожее со своим проектом Python, единственные вещи, которые я добавил бы:
Я лично использую, взаимодействует через интерфейс много в сочетании с Компонентной архитектурой Zope (ZCA). Преимущество не так, чтобы иметь интерфейсы, но смочь использовать их с адаптерами и утилитами (одиночные элементы).
, Например, Вы могли создать адаптер, который может посещать урок, который реализует ISomething, но адаптирует его к некоторому интерфейсу ISomethingElse. В основном это - обертка.
исходный класс был бы:
class MyClass(object):
implements(ISomething)
def do_something(self):
return "foo"
Затем предполагают, что интерфейс ISomethingElse имеет метод do_something_else (). Адаптер мог быть похожим на это:
class SomethingElseAdapter(object):
implements(ISomethingElse)
adapts(ISomething)
def __init__(self, context):
self.context = context
def do_something_else():
return self.context.do_something()+"bar"
Вы затем зарегистрировали бы тот адаптер в реестре компонента, и Вы могли затем использовать его как это:
>>> obj = MyClass()
>>> print obj.do_something()
"foo"
>>> adapter = ISomethingElse(obj)
>>> print adapter.do_something_else()
"foobar"
то, Что это дает Вам, является способностью расширить исходный класс с помощью функциональности, которую класс не обеспечивает непосредственно. Можно сделать это, не изменяя тот класс (это могло бы быть в другом продукте/библиотеке), и Вы могли просто обмениваться тем адаптером другой реализацией, не изменяя код, который использует его. Это все сделано регистрацией компонентов во время инициализации.
Это, конечно, главным образом полезно для платформ/библиотек.
я думаю, что это занимает время для привыкания к нему, но я действительно не хочу жить без него больше. Но, как сказано, прежде чем это будет также верно, что необходимо думать точно, где это имеет смысл и где это не делает. Конечно, интерфейсы на своем собственном могут также уже быть полезными как документация API. Для модульных тестов также полезно, где можно протестировать, если класс на самом деле реализует тот интерфейс. И наконец, что не менее важно, мне нравится запускаться путем записи интерфейса и некоторого doctests для получения идеи того, что я на самом деле собираюсь кодировать.
Для получения дополнительной информации можно проверить мой мало введения в него и существует довольно обширное описание, он - API.
Глиф Lefkowitz (Скрученной известности) просто недавно написал статью об этой теме . Лично я не чувствую потребность в интерфейсах, но YMMV.
Вы смотрели PyProtocols? у него есть хорошая реализация интерфейса, на которую вам стоит обратить внимание.