Как и в любом другом языке, в Ruby есть интерфейсы.
Обратите внимание, что вы должны быть осторожны, чтобы не смешивать концепцию Интерфейса, которая представляет собой абстрактную спецификацию обязанностей, гарантий и протоколов подразделения, с концепцией interface
, которая является ключевым словом в Языки программирования Java, C# и VB.NET. В Ruby мы постоянно используем первое, но второго просто не существует.
Очень важно различать их. Важен Интерфейс, а не interface
. interface
не говорит вам практически ничего полезного. Ничто не демонстрирует это лучше, чем маркерные интерфейсы в Java, то есть интерфейсы, вообще не имеющие членов: взгляните на java.io.Serializable
и java.lang.Cloneable
; эти два interface
означают очень разные вещи, но имеют одинаковую сигнатуру.
Итак, если два interface
, которые означают разные вещи, имеют одинаковую подпись, что точно гарантирует вам interface
?
Еще один хороший пример:
interface ICollection<T>: IEnumerable<T>, IEnumerable
{
void Add(T item);
}
Что такое Интерфейс для System.Collections.Generic.ICollection<T>.Add
?
- что длина коллекции не уменьшается
- что все предметы, которые были в коллекции раньше, все еще там
- что
item
есть в коллекции
И что из этого на самом деле появляется в interface
? Никто! В interface
нет ничего, что говорило бы о том, что метод Add
вообще должен добавлять, он мог бы с тем же успехом удалить элемент из коллекции.
Это совершенно правильная реализация этого interface
:
class MyCollection<T>: ICollection<T>
{
void Add(T item)
{
Remove(item);
}
}
Другой пример: где в 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
, который реализует тот же Интерфейс< /em> как IO
и, следовательно, большая часть Интерфейса File
, но без общего предка, кроме Object
.
person
Jörg W Mittag
schedule
17.08.2010