У Ruby есть интерфейсы, как и у любого другого языка.
Обратите внимание, что вы должны быть осторожны, чтобы не объединить концепцию интерфейса , которая является абстрактной спецификацией обязанностей, гарантий и протоколов модуля, с концепцией, interface
которая является ключевым словом в программировании на Java, C # и VB.NET. языков. В Ruby мы все время используем первое, а второго просто не существует.
Это очень важно различать. Важен интерфейс , а не файл interface
. interface
Не говорит вам , довольно много ничего полезного. Ничто не демонстрирует это лучше, чем интерфейсы маркеров в Java, которые являются интерфейсами, не имеющими вообще никаких членов: просто взгляните на java.io.Serializable
и java.lang.Cloneable
; эти два interface
символа означают очень разные вещи, но имеют одинаковую подпись.
Так, если два 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, вся соответствующая информация находится в документации, а не в типах. Итак, если типы все равно ничего интересного вам не говорят, зачем их вообще оставлять? Почему бы не придерживаться только документации? И это именно то, что делает Руби.
Обратите внимание, что есть и другие языки, на которых интерфейс может быть описан содержательно. Однако эти языки обычно не вызывают конструкцию, описывающую интерфейс "interface
", они называют ее type
. В языке программирования с зависимой типизацией вы можете, например, выразить свойства, которые sort
функция возвращает коллекцию той же длины, что и оригинал, что каждый элемент, который находится в оригинале, также находится в отсортированной коллекции и что нет большего элемента появляется перед меньшим элементом.
Итак, вкратце: Ruby не имеет эквивалента Java interface
. Однако у него есть эквивалент Java интерфейса , и он точно такой же, как в документации Java :.
Также, как и в Java, приемочные тесты можно использовать для указания интерфейсов. .
В частности, в Ruby интерфейс объекта определяется тем, что он может делать , а не тем, что class
есть или что module
он смешивает. К любому объекту, имеющему <<
метод, можно присоединить. Это очень полезно в модульных тестах, где вы можете просто передать Array
или String
вместо более сложного Logger
, хотя Array
и Logger
не делиться явным, interface
кроме того факта, что у них обоих есть вызываемый метод <<
.
Другой пример может служить StringIO
, который реализует тот же интерфейс , как IO
и , следовательно , большая часть интерфейса из File
, но без какого - либо совместного общего предка , кроме Object
.