visual tutorial studio sharp polimorfismo interfaces curso clases abstractas c# ruby interface contract equivalent

tutorial - En Ruby, ¿cuál es el equivalente a una interfaz en C#?



polimorfismo c# (6)

Jorg tiene un buen punto, Ruby tiene interfaces, pero no la palabra clave. Al leer algunas de las respuestas, creo que esto es negativo en los idiomas dinámicos. En lugar de imponer una interfaz a través del lenguaje, debe crear pruebas unitarias en lugar de que no se implementen los métodos de captura de un compilador. También hace que el método de comprensión sea más difícil de razonar, ya que tiene que rastrear qué es un objeto cuando está tratando de llamarlo.

Tomemos como ejemplo:

def my_func(options) ... end

Si observa la función, no tiene idea de qué opciones son ni a qué métodos o propiedades debería llamar, sin buscar las pruebas unitarias, a otros lugares en los que se llama e incluso consulte el método. Peor aún, es posible que el método ni siquiera use esas opciones sino que las pase a otros métodos. Por qué escribir pruebas unitarias cuando esto debería haber sido capturado por un compilador. El problema es que debe escribir el código de manera diferente para expresar esta desventaja en lenguajes dinámicos.

Sin embargo, hay una ventaja de esto, y es que los lenguajes de programación dinámicos son RÁPIDOS para escribir un fragmento de código. No tengo que escribir ninguna declaración de interfaz y más tarde puedo usar nuevos métodos y parámetros sin tener que ir a la interfaz para exponerla. Las compensaciones son la velocidad para el mantenimiento.

Actualmente estoy tratando de aprender a Ruby y estoy tratando de entender más sobre lo que ofrece en términos de encapsulación y contratos.

En C # se puede definir un contrato usando una interfaz. Una clase que implementa la interfaz debe cumplir los términos del contrato al proporcionar una implementación para cada método y propiedad (y quizás otras cosas) definidas. La clase individual que implementa una interfaz puede hacer lo que necesite dentro del alcance de los métodos definidos por el contrato, siempre que acepte los mismos tipos de argumentos y devuelva el mismo tipo de resultado.

¿Hay alguna manera de imponer este tipo de cosas en Ruby?

Gracias

Un ejemplo simple de lo que quiero decir en C #:

interface IConsole { int MaxControllers {get;} void PlayGame(IGame game); } class Xbox360 : IConsole { public int MaxControllers { get { return 4; } } public void PlayGame(IGame game) { InsertDisc(game); NavigateToMenuItem(); Click(); } } class NES : IConsole { public int MaxControllers { get { return 2; } } public void PlayGame(IGame game) { InsertCartridge(game); TurnOn(); } }


Las interfaces generalmente se introducen en lenguajes OO de tipo estático para compensar la falta de herencia múltiple. En otras palabras, son más un mal necesario que algo útil per se .

Ruby, por otro lado:

  1. Es un lenguaje tipificado dinámicamente con "tipografía pato", por lo que si desea llamar al método foo en dos objetos, no es necesario que hereden la misma clase ancestral ni implementen la misma interfaz.
  2. Admite la herencia múltiple a través del concepto de mixins, una vez más, no hay necesidad de interfaces aquí.

No hay interfaces en ruby, ya que ruby ​​es un lenguaje de tipo dinámico. Las interfaces se utilizan básicamente para hacer diferentes clases intercambiables sin romper la seguridad de los tipos. Su código puede funcionar con cada consola siempre que se comporte como una consola que en C # significa que implementa IConsole. "duck typing" es una palabra clave que puede utilizar para ponerse al día con la forma en que los idiomas dinámicos tratan este tipo de problema.

Además, puede y debe escribir pruebas unitarias para verificar el comportamiento de su código. Cada objeto tiene un respond_to? Método que puede utilizar en su afirmación.


Ruby realmente no los tiene; Las interfaces y los contratos generalmente viven más en el mundo estático que en la dinámica.

Hay una gema llamada Handshake que puede implementar contratos informales, si realmente lo necesita.


Ruby tiene interfaces como cualquier otro idioma.

Tenga en cuenta que debe tener cuidado de no confundir el concepto de Interfaz , que es una especificación abstracta de las responsabilidades, garantías y protocolos de una unidad con el concepto de la interface que es una palabra clave en Java, C # y VB.NET. lenguajes de programación. En Ruby, usamos el primero todo el tiempo, pero el último simplemente no existe.

Es muy importante distinguir los dos. Lo importante es la interfaz , no la interface . La interface te dice nada útil. Nada demuestra esto mejor que las interfaces de marcadores en Java, que son interfaces que no tienen ningún miembro en absoluto: simplemente eche un vistazo a java.io.Serializable y java.lang.Cloneable ; esas dos interface significan cosas muy diferentes, pero tienen la misma firma exacta .

Entonces, si dos interface que tienen diferentes significados tienen la misma firma, ¿ qué es exactamente lo que la interface garantiza?

Otro buen ejemplo:

interface ICollection<T>: IEnumerable<T>, IEnumerable { void Add(T item); }

¿Qué es la interfaz de System.Collections.Generic.ICollection<T>.Add ?

  • Que la longitud de la colección no disminuya.
  • que todos los elementos que estaban en la colección antes todavía están allí
  • ese item está en la colección

¿Y cuál de los que realmente aparece en la interface ? ¡Ninguna! No hay nada en la interface que diga que el método Add debe incluso agregarse en absoluto, igual podría eliminar un elemento de la colección.

Esta es una implementación perfectamente válida de esa interface :

class MyCollection<T>: ICollection<T> { void Add(T item) { Remove(item); } }

Otro ejemplo: ¿dónde en java.util.Set<E> realmente dice que es, ya sabes, un conjunto ? ¡En ninguna parte! O más precisamente, en la documentación. En inglés.

En casi todos los casos de interfaces , tanto de Java como de .NET, toda la información relevante está en realidad en los documentos, no en los tipos. Entonces, si los tipos no te dicen nada interesante de todos modos, ¿por qué conservarlos? ¿Por qué no atenerse sólo a la documentación? Y eso es exactamente lo que hace Ruby.

Tenga en cuenta que hay otros idiomas en los que la interfaz se puede describir de una manera significativa. Sin embargo, esos idiomas generalmente no llaman a la construcción que describe la " interface " de la interface , lo llaman type . En un lenguaje de programación de tipo dependiente, puede, por ejemplo, expresar las propiedades que una función de sort devuelve una colección de la misma longitud que el original, que cada elemento que está en el original también está en la colección ordenada y que no aparece ningún elemento más grande antes de un elemento más pequeño.

Entonces, en resumen: Ruby no tiene un equivalente a una interface Java. Sin embargo, tiene un equivalente a una interfaz Java, y es exactamente el mismo que en Java: documentación.

Además, al igual que en Java, las Pruebas de aceptación también se pueden utilizar para especificar las interfaces .

En particular, en Ruby, la Interfaz de un objeto está determinada por lo que puede hacer , no por qué class es o por qué module se mezcla. Cualquier objeto que tenga un método << puede ser agregado. Esto es muy útil en pruebas unitarias, donde simplemente puede pasar un Array o una String lugar de un Logger más complicado, aunque Array y Logger no comparten una interface explícita interface aparte del hecho de que ambos tienen un método llamado << .

Otro ejemplo es StringIO , que implementa la misma Interfaz que IO y, por lo tanto, una gran parte de la Interfaz de File , pero sin compartir ningún ancestro común además del Object .