Domanda

Al momento sto cercando di imparare Ruby e sto cercando di capire di più su ciò che offre in termini di incapsulamento e contratti.

In C # un contratto può essere definito utilizzando un'interfaccia. Una classe che implementa l'interfaccia deve soddisfare le condizioni all'interno del contratto, fornendo un'implementazione per ciascun metodo e proprietà (e forse altre cose) definito. La classe individuo che implementa un'interfaccia possono fare ciò di cui ha bisogno nell'ambito di applicazione dei metodi definiti dal contratto, a patto che accetti gli stessi tipi di argomenti e restituisce lo stesso tipo di risultato.

C'è un modo per far rispettare questo genere di cose in Ruby?

Grazie

  

Un semplice esempio di ciò che intendo in 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();
   }
}
È stato utile?

Soluzione

Non ci sono interfacce in rubino dal rubino è un linguaggio tipizzato in modo dinamico. Interfacce sono fondamentalmente utilizzati per rendere classi diverse intercambiabile senza rompersi sicurezza tipo. Il tuo codice può lavorare con tutte le console il più a lungo si comporta come una console, che in C # mezzi attrezzi IConsole. "Duck typing" è una parola chiave è possibile utilizzare per recuperare il ritardo con il linguaggi dinamici modo di trattare con questo tipo di problema.

Inoltre si può e deve scrivere unit test per verificare il comportamento del codice. Ogni oggetto ha un metodo respond_to? è possibile utilizzare nel vostro assert.

Altri suggerimenti

Ruby ha Interfacce , proprio come qualsiasi altra lingua.

Nota non che bisogna stare attenti a confondere il concetto di Interfaccia , che è una specifica astratta delle responsabilità, garanzie e protocolli di un'unità con il concetto di interface che è un parola chiave nel Java, C # e VB.NET linguaggi di programmazione. In Ruby, usiamo l'ex tutto il tempo, ma quest'ultimo semplicemente non esiste.

E 'molto importante distinguere i due. Quello che è importante è il Interfaccia , non il interface. Il interface ti dice praticamente nulla di utile. Nulla lo dimostra meglio del Marker interfacce in Java, che sono interfacce che non hanno membri a tutti: basta dare un'occhiata a java.io.Serializable e java.lang.Cloneable ; quei due interfaces significano molto cose diverse, eppure hanno il esattamente lo stesso firma.

Quindi, se due interfaces che le cose medi diverse, hanno la stessa firma, che cosa esattamente è il interface anche garantendovi?

Un altro buon esempio:

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

Qual è la Interfaccia di System.Collections.Generic.ICollection<T>.Add ?

  • che la lunghezza della collezione non diminuisce
  • che tutti gli elementi che erano nella collezione prima che sono ancora lì
  • che item è nella collezione

E che di quegli spettacoli in realtà nella interface? Nessuna! Non c'è nulla nella interface che dice che il metodo Add deve anche Aggiungi a tutti, potrebbe altrettanto bene Rimuovi un elemento della collezione.

Questo è un perfettamente valida attuazione di tale interface:

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

Un altro esempio: dove nel java.util.Set<E> vuol davvero dire che è, si sa, un set ? Da nessuna parte! O più precisamente, nella documentazione. In inglese.

In quasi tutti i casi di interfaces, sia da Java e .NET, tutto il rilevanti informazioni è in realtà nella documentazione, non nei tipi. Quindi, se i tipi non dicono nulla di interessante in ogni caso, perché tenerli a tutti? Perché non attaccare solo alla documentazione? E questo è esattamente quello che fa Ruby.

Si noti che ci sono altri lingue in cui il Interfaccia può effettivamente essere descritto in modo significativo. Tuttavia, queste lingue in genere non chiamano il costrutto che descrive il Interfaccia "interface", lo chiamano type. In un linguaggio di programmazione dipendente tipizzato, è possibile ad esempio esprimere le proprietà che una funzione sort restituisce un insieme della stessa lunghezza dell'originale, che ogni elemento che è in originale è anche nella raccolta differenziata e che non appare elemento più grandi prima di un elemento più piccolo.

Così, in breve: Rubino non ha un equivalente ad un interface Java. E ' ha tuttavia avere un equivalente ad un Java Interfaccia , e la sua esattamente come in Java:. Documentazione

Inoltre, proprio come in Java, Test di collaudo può essere utilizzato per specificare Interfaccia S pure.

In particolare, in rubino, il Interfaccia di un oggetto è determinato da ciò che possono do , non quello class si è, o quali module mescola in. Qualsiasi oggetto che ha un metodo << può essere aggiunto a. Questo è molto utile nel test di unità, dove si can semplicemente passano in un Array o un String al posto di un Logger più complicata, anche se Array e Logger non condividono un interface esplicito a parte il fatto che entrambi hanno un metodo chiamato <<.

Un altro esempio è StringIO , che implementa la stessa Interfaccia come IO e quindi una grande porzione del Interfaccia di File, ma senza condividere alcun antenato comune oltre Object.

Interfacce di solito sono introdotti ai linguaggi OO digitato statiche, al fine di compensare la mancanza di ereditarietà multipla. In altre parole, sono più di un male necessario che qualcosa di utile per se .

Ruby, d'altra parte:

  1. è dinamicamente tipizzato lingua con "duck typing", quindi se si desidera chiamare il metodo foo su due oggetti, non hanno bisogno di nessuno eredita stessa classe antenata, né implementare la stessa interfaccia.
  2. supporta l'ereditarietà multipla attraverso concetto di mixins, ancora una volta senza necessità di interfacce qui.

Ruby non hanno davvero di loro; interfacce e contratti in genere vivono più nel mondo statico, piuttosto che la dinamica.

C'è una gemma chiamata Stretta di mano in grado di implementare i contratti informali, se si ha realmente bisogno.

rubino utilizza il concetto di moduli come stand-in (pò) per le interfacce. Design Patterns in Ruby ha un sacco di veramente grandi esempi sulle differenze tra i due concetti e perché rubino sceglie l'alternativa più flessibile alle interfacce.

http://www.amazon.com/Design-Patterns-Ruby-Russ -Olsen / dp / 0321490452

Jorg ha un buon punto, Ruby ha interfacce, non solo la parola chiave. Nel letto alcune delle risposte, credo che questo è un aspetto negativo in linguaggi dinamici. Invece di far rispettare un'interfaccia attraverso il linguaggio, è necessario creare unit test invece di avere un compilatore metodi di cattura non in corso di attuazione. E 'anche il metodo comprensione più difficile ragionare su, come si deve dare la caccia a quello che un oggetto è quando si sta cercando di chiamarlo.

Prendete come esempio:

def my_func(options)
  ...
end

Se si guarda alla funzione, non avete idea di cosa opzioni è e quali metodi o proprietà che dovrebbe chiamare, senza la caccia per i test di unità, in altri luoghi è chiamato, e ancora di guardare il metodo. Peggio ancora, il metodo può anche non utilizzare queste opzioni, ma passarlo a ulteriori metodi. Perché unità di scrivere i test quando questo avrebbe dovuto essere catturato da un compilatore. Il problema è che è necessario scrivere codice in modo diverso per esprimere questo aspetto negativo in linguaggi dinamici.

C'è un rialzo per questo, però, e questo è linguaggi di programmazione dinamici sono FAST per scrivere un pezzo di codice. Non ho di scrivere qualsiasi dichiarazione di interfaccia e poi posso nuovi metodi e parametri senza andare al interfaccia per esporlo. I compromessi sono la velocità per la manutenzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top