Ruby tem interfaces como qualquer outra linguagem.
Observe que você deve ter cuidado para não confundir o conceito de Interface , que é uma especificação abstrata das responsabilidades, garantias e protocolos de uma unidade com o conceito de interface
que é uma palavra-chave na programação Java, C # e VB.NET línguas. Em Ruby, usamos o primeiro o tempo todo, mas o último simplesmente não existe.
É muito importante distinguir os dois. O que é importante é a interface , não o interface
. O não interface
diz nada de útil. Nada demonstra isso melhor do que as interfaces de marcador em Java, que são interfaces que não possuem nenhum membro: basta dar uma olhada em java.io.Serializable
e java.lang.Cloneable
; esses dois interface
significam coisas muito diferentes, embora tenham exatamente a mesma assinatura.
Então, se dois interface
s que significam coisas diferentes têm a mesma assinatura, o que exatamente o interface
par está garantindo a você?
Outro bom exemplo:
package java.util;
interface List<E> implements Collection<E>, Iterable<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException;
}
Qual é a interface de java.util.List<E>.add
?
- que o comprimento da coleção não diminua
- que todos os itens que estavam na coleção antes ainda estão lá
- que
element
está na coleção
E qual desses realmente aparece no interface
? Nenhum! Não há nada no interface
que diz que o Add
método deve mesmo adicionar , ele também pode remover um elemento da coleção.
Esta é uma implementação perfeitamente válida de que interface
:
class MyCollection<E> implements java.util.List<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException {
remove(element);
}
}
Outro exemplo: onde java.util.Set<E>
realmente diz que é, você sabe, um conjunto ? Lugar algum! Ou mais precisamente, na documentação. Em inglês.
Em praticamente todos os casos de interfaces
, tanto do Java quanto do .NET, todas as informações relevantes estão na verdade nos documentos, não nos tipos. Portanto, se os tipos não dizem nada de interessante, por que mantê-los? Por que não ficar apenas com a documentação? E é exatamente isso que Ruby faz.
Observe que existem outras linguagens nas quais a Interface pode realmente ser descrita de uma forma significativa. No entanto, essas linguagens normalmente não chamam a construção que descreve a Interface " interface
", eles a chamam type
. Em uma linguagem de programação de tipo dependente, você pode, por exemplo, expressar as propriedades de que uma sort
função retorna uma coleção do mesmo comprimento que o original, que cada elemento que está no original também está na coleção classificada e que nenhum elemento maior aparece antes de um elemento menor.
Resumindo: Ruby não tem equivalente a Java interface
. Ele faz , no entanto, tem um equivalente a um Java interface , e é exatamente o mesmo que em Java: documentação.
Além disso, assim como em Java, os testes de aceitação também podem ser usados para especificar interfaces .
Em particular, em Ruby, a Interface de um objeto é determinada pelo que ele pode fazer , não o que class
é ou o que module
ele se mistura. Qualquer objeto que tenha um <<
método pode ser anexado. Isso é muito útil em testes de unidade, onde você pode simplesmente passar um Array
ou um em String
vez de um mais complicado Logger
, embora Array
e Logger
não compartilhe um explícito, interface
exceto pelo fato de que ambos têm um método chamado <<
.
Outro exemplo é StringIO
, que implementa a mesma interface como IO
e, portanto, uma grande porção da interface de File
, mas sem qualquer partilha ancestral comum além Object
.