Подтвердить что ты не робот

Почему нам не нужны интерфейсы в динамических языках?

Это только из-за динамической типизации, мы не требуем концепции интерфейсов (например, в Java и С#) в python?

4b9b3361

Ответ 1

interface как ключевое слово и артефакт был введен Java 1 (и С# взял его оттуда), чтобы описать, что должен был заключить контракт, которым должен обладать объект.

Но интерфейс всегда был ключевой частью объектно-ориентированной парадигмы и в основном представляет методы, с которыми объект должен отвечать. Java просто применяет этот механизм для обеспечения статической проверки типов.

Итак, динамические (OO) языки программирования do используют интерфейсы, даже если они не статически проверяют их. Как и другие типы данных, например, в Ruby:

 @i = 1;

Вам не нужно объявлять i типа FixNum, который вы просто используете. То же самое касается интерфейсов, они просто текут. Компромисс заключается в том, что вы не можете статически проверять это, и сбои отображаются только во время выполнения.

С другой стороны Структурный тип (или статический тип утки, как я его называю: P), используемый языками как Go или Scala, дает лучшее из обоих миров.

<суб > 1. См. Комментарий Дэниела Эрвикера о ключевом слове CORBA interface

суб >

Ответ 2

Мы не требуем их, но мы их поддерживаем. Проверьте Zope Interfaces (который может быть и используется вне Zope).

Ответ 3

Конструкции интерфейса используются в статически типизированных языках для обучения системе типов, какие объекты подставляются друг для друга в конкретном контексте вызова метода. Если два объекта реализуют один и тот же метод, но не связаны через наследование из общего базового класса или реализации общего интерфейса, система типов будет вызывать ошибку во время компиляции, если вы замените ее на другую.

В динамических языках используется "утиная печать", что означает, что метод просто просматривается во время выполнения, и если он существует с правильной подписью, он используется; в противном случае возникает ошибка времени выполнения. Если два объекта "quack like a duck", реализуя один и тот же метод, они заменяются. Таким образом, нет явной потребности в том, чтобы язык связывал их через базовый класс или интерфейс.

Как говорится, интерфейсы как концепция по-прежнему очень важны в динамическом мире, но они часто просто определяются в документации и не применяются языком. Иногда я вижу, что программисты действительно создают базовый класс, который также набросает интерфейс для этой цели; это помогает формализовать документацию и особенно полезно, если часть интерфейса может быть реализована с точки зрения остальной части интерфейса.

Ответ 4

Стоит отметить, что, вопреки тому, что многие люди скажут в качестве первого ответа, интерфейсы могут использоваться, чтобы сделать больше, чем документ "какие методы поддерживает класс". Грзенио затрагивает это своей формулировкой о "реализации такого же поведения". В качестве конкретного примера рассмотрим интерфейс Java Serializable. Он не реализует никаких методов; скорее он используется как "маркер", чтобы указать, что класс может быть сериализован безопасно.

Когда рассматривается этот способ, может быть разумным иметь динамический язык, который использует интерфейсы. Считая, что нечто похожее на аннотации может быть более разумным.

Ответ 5

Одна из ключевых особенностей, по крайней мере, некоторых динамических языков, которые делают явные интерфейсы более чем неудобными, заключается в том, что динамические языки могут часто отвечать на сообщения (err, "вызовы методов" ), о которых они не знают заранее, даже делая что-то как создание методов "на лету". Единственный реальный способ узнать, правильно ли реагирует объект на сообщение, - это отправить ему сообщение. Это нормально, потому что динамические языки считают лучше поддерживать такую ​​вещь, а не статическую проверку типа; объект считается пригодным для использования в конкретном протоколе, поскольку он "известен", чтобы иметь возможность участвовать в этом протоколе (например, в силу предоставления другим сообщением).

Ответ 7

Интерфейсы используются в статически типизированных языках для описания того, что два иначе независимых объекта "реализуют одно и то же поведение". В динамически типизированных языках одно неявно предполагает, что, когда у двух объектов есть метод с тем же именем /params, он делает то же самое, поэтому интерфейсы бесполезны.

Ответ 8

В С# и Java интерфейсы являются просто абстрактными классами со всеми абстрактными методами. Они существуют, чтобы допускать псевдо множественное наследование без фактического поддержки полномасштабного множественного наследования и множественного наследования неоднозначности.

Python поддерживает множественное наследование и имеет свой собственный способ определения того, какой родительский метод следует вызывать, когда метод существует у нескольких родителей.

Ответ 9

Динамические языки Duck Typed

Если он ходит как утка и шарлатанцы как утка, это должна быть утка

http://en.wikipedia.org/wiki/Duck_typing

Другими словами, если вы выставляете объект для поддержки метода Delete(), вы можете просто использовать

obj.Delete()

но если объект не поддерживает Delete(), вы получаете ошибку Runtime. Статически типизированные языки не позволят этого и бросают ошибку времени компиляции. Таким образом, вы в основном торгуете типом safty против более быстрого времени разработки и гибкости.

Без интерфейсов вы можете сделать что-то подобное на статических языках:

void Save(MyBaseClass item)
{
    if (item.HasChanges)
        item.Save()
}

но для каждого объекта, который вы передаете этому методу, потребуется унаследовать от MyBaseClass. Поскольку Java или С# не поддерживают muliinheritance, что не очень гибко, потому что если ваш класс уже наследует другой класс, он также не может наследовать от MyBaseClass. Поэтому лучшим выбором будет создание интерфейса ISavable и принятие этого в качестве входного параметра для обеспечения сохранения элемента. Тогда у вас есть лучшее из обоих: тип безопасности и гибкость.

public interface ISavable
{
    bool HasChanges {get;set;}
    void Save();
}

void Save(ISavable item)
{
    if (item.HasChanges)
        item.Save()
}

Последний бэкдор должен использовать объект как параметр, если вы не можете ожидать, что каждый элемент, который будет использовать ваш метод сохранения, будет реализовывать интерфейс.

void Save(object item)
{
    if (item.HasChanges)
        item.Save()
}

Но чем снова вы не проверяете время компиляции и, вероятно, получаете ошибку выполнения, если кто-то использует ваш метод с несовместимым классом.