2016-07-02 9 views
6

Sto leggendo il mio libro rubino. Guardando il codice sottostante,Quali criteri giustificano l'utilizzo di un modulo su una classe in Ruby?

module Destroy 
    def destroy(anyObject) 
    @anyObject = anyObject 
    puts "I will destroy the object: #{anyObject}" 
    end 
end 

class User 
    include Destroy 
    attr_accessor :name, :email 
    def initialize(name,email) 
    @name = name 
    @email = email 
    end 
end 

my_info = User.new("Bob","[email protected]") 
puts "So your name is: #{my_info.name} and you have email #{my_info.email}" 

user = User.new("john","[email protected]") 
user.destroy("blah") 

Avrei potuto creare un altro metodo all'interno della mia classe. Perché dovrei voler fare questo? Perché dovrei voler usare un modulo? Non è come incorporare questo in altre classi è più facile che usare semplicemente l'ereditarietà normale.

+0

L'ereditarietà non è l'unico modo per condividere funzionalità e spesso non è né pratica né possibile. –

+0

Possibile duplicato di [Differenza tra una classe e un modulo] (http://stackoverflow.com/questions/151505/difference-between-a-class-and-a-module) – SoAwesomeMan

risposta

3

Si può pensare a un modulo e ai metodi e alle costanti al suo interno più come fornire funzioni di utilità e azioni che è possibile includere in altri oggetti come si ritiene opportuno. Per esempio, se si desidera utilizzare la funzione distruggere negli oggetti Foo e Bar si farebbe simile:

class Foo 
    include Destroy 
    # other code below 
end 

class Bar 
    include Destroy 
    # other code below 
end 

Ora, qualsiasi oggetto o FooBar ha accesso a tutti i metodi o costanti all'interno di distruggere.

I moduli definiscono uno spazio dei nomi, una sandbox in cui i vostri metodi e costanti possono giocare senza doversi preoccupare di essere calpestati da altri metodi e costanti. Il ruby docs va più in profondità su questo e include un buon esempio pratico di quando si vorrebbe usarlo come si vede qui sotto:

module Debug 
    def whoAmI? 
    "#{self.type.name} (\##{self.id}): #{self.to_s}" 
    end 
end 
class Phonograph 
    include Debug 
    # ... 
end 
class EightTrack 
    include Debug 
    # ... 
end 
ph = Phonograph.new("West End Blues") 
et = EightTrack.new("Surrealistic Pillow") 
ph.whoAmI? » "Phonograph (#537766170): West End Blues" 
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow" 

In questo esempio, ogni classe che comprende Debug ha accesso al metodo whoAmI? e altri metodi e costanti inclusi in Debug senza ridefinirlo per ogni classe.

+0

"# {self.type.name} (\ ## {self.id}): # {self.to_s}", cosa significa questa riga? Il mio libro parla di sé molto brevemente, punti autonomi del modulo Debug qui giusto? –

+0

In particolare anche i segni ##, mai visto nella mia vita, sono solo familiare con # {variabile} –

+0

@cresjoy. È una stringa contenente il nome del tipo, l'id e una rappresentazione di stringa dell'oggetto. Il numero extra è solo per la formattazione, come si vede nelle ultime due righe dell'esempio, ed è per questo che è sfuggito. Il sé usa l'oggetto chiamato per restituire l'informazione. – Dom

2

Alcuni linguaggi di programmazione come C++, Perl e Python consentono a una classe di ereditare da più altre classi; è chiamato ereditarietà multipla. Ruby non supporta l'ereditarietà multipla. Ciò significa che ogni classe può ereditare solo da un'altra classe. Tuttavia, ci sono casi in cui una classe trarrebbe vantaggio dall'acquisizione di metodi definiti all'interno di più altre classi. Ciò è reso possibile dall'uso di un costrutto chiamato modulo.

Un modulo è in qualche modo simile a una classe, tranne che non supporta l'ereditarietà, né l'istanziazione. Viene utilizzato principalmente come contenitore per la memorizzazione di più metodi. Un modo per usare un modulo è utilizzare un'istruzione di inclusione o di estensione all'interno di una classe. In questo modo, la classe ottiene l'accesso a tutti i metodi e gli oggetti definiti all'interno del modulo. Si dice che il modulo sia mescolato nella classe. Quindi, un mixin è solo un modulo incluso in una classe. Un singolo modulo può essere mescolato in più classi e una singola classe può mescolarsi in più moduli; quindi, qualsiasi limitazione imposta dal modello di ereditarietà di Ruby viene eliminata dalla funzione mixin.

I moduli possono essere utilizzati anche per il namespace. Questo è spiegato in this post at the Practicing Ruby website.

+0

Buoni punti, ma dovresti dire qualcosa su moduli che non sono intesi per essere mixin, ma semplicemente per ospitare i metodi helper (module) (definiti 'def self.mod_method ...') che potrebbero essere usati da varie classi. –

+0

Hmm .. Totalmente non lo sapevo. Quindi affermando che se la Classe B eredita dalla classe A, la classe C non può ereditare dalla classe A? –

+0

@cresjoy No. Entrambe le classi B e C possono ereditare da A. Tuttavia, B non può ereditare sia da A che da C. Ogni classe può ereditare solo da un'altra classe. Tuttavia, una classe può essere ereditata da più altre classi. – BrunoFacca

0

Si sta scrivendo un modulo nello stesso file della classe, ma non necessariamente all'interno della classe, ma comunque.

Per me ci sono 3 motivi per utilizzare un modulo (maggiori dettagli here):

  1. moduli forniscono uno spazio dei nomi e prevenire nome scontri.
  2. I moduli implementano la funzione di mixaggio.
  3. Quando si dispone di una classe molto complessa e densa, è possibile dividerla in moduli e includerli nella classe principale.

Il tuo esempio è abbastanza semplice, sarebbe davvero più sensato scrivere il metodo nella classe stessa, ma provare a immaginare uno scenario complesso.

+1

Il tuo 1 è irrilevante qui. 2 è anche irrilevante se lo scopo è quello di includere la struttura in più classi e, in caso contrario, non spiega nulla. 3 è il caso pertinente in questione, ma non sta spiegando perché lo si voglia fare. – sawa

+0

Indipendentemente da questo scenario, penso che sia importante che l'OP sappia perché e quando userebbe un modulo. – fabriciofreitag