Ruby имеет Интерфейсы , как и любой другой язык.
Обратите внимание, что вы должны быть осторожны, чтобы не смешивать понятие Интерфейс , который является абстрактнымспецификация обязанностей, гарантий и протоколов единицы с понятием interface
, которое является ключевым словом в языках программирования Java, C # и VB.NET.В Ruby мы все время используем первое, но второго просто не существует.
Очень важно различать два.Что важно, это Интерфейс , а не interface
.interface
говорит вам почти ничего полезного.Ничто не демонстрирует это лучше, чем маркерные интерфейсы в Java, которые являются интерфейсами, которые вообще не имеют членов: просто взгляните на java.io.Serializable
и java.lang.Cloneable
;эти два interface
s означают очень разные вещи, но они имеют точно такую же подпись.
Итак, если два interface
s означают разные вещи,имеют такую же подпись, что точно является interface
даже гарантирующим вас?
Еще один хороший пример:
package java.util;
interface List<E> implements Collection<E>, Iterable<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException;
}
Что такое Интерфейс из java.util.List<E>.add
?
- , что длина коллекции не уменьшается
- что все элементы, которые были в коллекции до этого, все еще там
- , что
element
находится в коллекции
И что из этого на самом деле появляется в interface
?Никто!В interface
нет ничего, что говорит о том, что метод Add
должен даже добавлять вообще, он может удалить элемент из коллекции.
Это совершенно правильная реализация этого interface
:
class MyCollection<E> implements java.util.List<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException {
remove(element);
}
}
Другой пример: где в java.util.Set<E>
действительно сказано, что это, вы знаете, набор ?Нигде!Точнее, в документации.На английском языке.
Практически во всех случаях interfaces
, как из Java, так и .NET, вся релевантная информация фактически находится в документах, а не в типах.Итак, если типы не говорят вам ничего интересного, зачем вообще их хранить?Почему бы не придерживаться только документации?И это именно то, что делает Ruby.
Обратите внимание, что есть другие языки, на которых Interface действительно может быть описан осмысленно.Однако эти языки обычно не вызывают конструкцию, которая описывает Interface"interface
", они называют ее type
.В языке программирования с зависимой типизацией вы можете, например, выразить свойства, что функция sort
возвращает коллекцию той же длины, что и оригинал, каждый элемент в оригинале также находится в отсортированной коллекции и чтоэлемент меньшего размера не появляется перед элементом меньшего размера.
Итак, вкратце: Ruby не имеет эквивалента Java interface
.Он имеет , однако, имеет эквивалент интерфейса Java , и он точно такой же, как в Java: документация.
Также, как и в Java, Приемочные тесты можно также использовать для указания Интерфейсов .
В частности, в Ruby Интерфейс объекта определяется тем, как онможет делать , не то, что есть class
, или что module
он смешивает. Любой объект, который имеет метод <<
, может быть добавлен.Это очень полезно в модульных тестах, где вы можете просто передать Array
или String
вместо более сложного Logger
, даже если Array
и Logger
не разделяют явное interface
, кромеиз-за того, что у них обоих есть метод с именем <<
.
Другой пример - StringIO
, который реализует тот же интерфейс , что и IO
, и, таким образом,большая часть интерфейса из File
, но без общего общего предка, кроме Object
.