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

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

17
задан Matchu 17 June 2010 в 14:47
поделиться

9 ответов

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

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

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

 @i = 1;

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

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

1. См. Комментарий Дэниела Эрвикера по поводу интерфейса CORBA ключевое слово

23
ответ дан 30 November 2019 в 12:19
поделиться

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

0
ответ дан 30 November 2019 в 12:19
поделиться

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

5
ответ дан 30 November 2019 в 12:19
поделиться

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

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

1
ответ дан 30 November 2019 в 12:19
поделиться

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

1
ответ дан 30 November 2019 в 12:19
поделиться

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

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

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

1
ответ дан 30 November 2019 в 12:19
поделиться

Динамические языки - это утиный тип.

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

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

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

obj.Delete()

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

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

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

но это потребует, чтобы каждый объект, который вы передаете этому методу, унаследовал от MyBaseClass. Поскольку Java или C # не поддерживают множественное наследование, это не очень гибко, потому что, если ваш класс уже наследует другой класс, он также не может наследовать от 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()
}

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

0
ответ дан 30 November 2019 в 12:19
поделиться

Perl has Roles (or traits), It is more than interfaces unlike java perl roles we can have a implementation check out these links for more on perl roles

1
ответ дан 30 November 2019 в 12:19
поделиться

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

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

0
ответ дан 30 November 2019 в 12:19
поделиться