Differenza tra una classe e un modulo


Risposte:


398

La prima risposta è buona e fornisce alcune risposte strutturali, ma un altro approccio è quello di pensare a quello che stai facendo. I moduli riguardano la fornitura di metodi che è possibile utilizzare in più classi: pensali come "librerie" (come vedresti in un'app Rails). Le lezioni riguardano gli oggetti; i moduli riguardano le funzioni.

Ad esempio, i sistemi di autenticazione e autorizzazione sono buoni esempi di moduli. I sistemi di autenticazione funzionano su più classi a livello di app (gli utenti sono autenticati, le sessioni gestiscono l'autenticazione, molte altre classi agiranno in modo diverso in base allo stato di autenticazione), quindi i sistemi di autenticazione agiscono come API condivise.

Puoi anche utilizzare un modulo quando hai metodi condivisi su più app (di nuovo, il modello di libreria è buono qui).


7
Il modulo è uguale alle interfacce in Java?
Saad Rehman Shah,

14
@Caffeine non proprio perché i moduli Ruby in realtà includono implementazioni, mentre le interfacce in Java sono astratte
Jorge Israel Peña,

8
No, i moduli e i pacchetti / JAR Java sono bestie completamente diverse.
Karoly Horvath,

9
Mi piacciono di più le lezioni astratte con l'implementazione del metodo.
Automatico,

2
In realtà, @Chole colpisce una delle cose belle dei moduli: Namespacing. Quindi mentre i moduli non sono un equivalente diretto dei pacchetti in Java, possono essere usati per ottenere qualcosa di simile: blog.rubybestpractices.com/posts/gregory/…
michaelok

513
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║               ║ class                     ║ module                          ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated       ║ can *not* be instantiated       ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage         ║ object creation           ║ mixin facility. provide         ║
║               ║                           ║   a namespace.                  ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass    ║ module                    ║ object                          ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods       ║ class methods and         ║ module methods and              ║
║               ║   instance methods        ║   instance methods              ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance   ║ inherits behaviour and can║ No inheritance                  ║
║               ║   be base for inheritance ║                                 ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion     ║ cannot be included        ║ can be included in classes and  ║
║               ║                           ║   modules by using the include  ║
║               ║                           ║   command (includes all         ║
║               ║                           ║   instance methods as instance  ║
║               ║                           ║   methods in a class/module)    ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension     ║ can not extend with       ║ module can extend instance by   ║
║               ║   extend command          ║   using extend command (extends ║
║               ║   (only with inheritance) ║   given instance with singleton ║
║               ║                           ║   methods from module)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝

Qual è la superclasse della classe 'Class'?
Aashish P

10
Ho ottenuto la gerarchia, Classe -> Modulo -> Oggetto -> BasicObject. Freddo!!
Aashish P

Perché "module consiste in" omettere le variabili, quando sia le classi che i moduli supportano le variabili di classe? Vedi risposta accettato di stackoverflow.com/questions/5690458/...~~V~~singular~~3rd
kaleidic

Molti diagrammi in tutte queste risposte. Un breve esempio: rubyfiddle.com/riddles/06081
Donato,

16
Come può un modulo "non essere istanziato" e tuttavia avere metodi di istanza?
devius,

91

Sono sorpreso che nessuno l'abbia ancora detto.

Dal momento che il richiedente proviene da un background Java (e anche io), ecco un'analogia che aiuta.

Le classi sono semplicemente come le classi Java.

I moduli sono come le classi statiche Java. Pensa alla Mathclasse in Java. Non lo installi e riutilizzi i metodi nella classe statica (ad es. Math.random()).


11
Ma i moduli possono anche aggiungere metodi di istanza alla classe inclusa, mentre le classi statiche in Java no.
Ripristina Monica - notmaynard,

4
Questa affermazione è vera anche proveniente da un pesante background in C #.
Damon Drake,

5
Questo non è del tutto vero; i moduli non hanno metodi statici, hanno solo metodi. I moduli possono "estendersi" (in realtà la sintassi extend self), rendendo i loro metodi disponibili per la loro selfmetaclasse. Ciò consente di inviare un metodo come random()su un Mathmodulo. Ma per loro natura, i metodi di un modulo non possono essere chiamati da soli self. Questo ha a che fare con la nozione di Ruby di self, le sue metaclasse e come funziona la ricerca dei metodi. Dai un'occhiata a "Metaprogramming Ruby" - Paolo Perlotta per i dettagli.
scottburton11,

Direi che i moduli sono più simili alle interfacce con i metodi (interfacce Java 8 con impl predefinito) ma non possono ereditare l'uno dall'altro a differenza delle interfacce Java
divideByZero il

In che modo questa risposta ha così tanti voti? btw che è stato detto in parole migliori 1MO prima: stackoverflow.com/a/17027346/986862
Andre Figueiredo

39

Fondamentalmente, il modulo non può essere istanziato. Quando una classe include un modulo, viene generata una superclasse proxy che fornisce l'accesso a tutti i metodi del modulo e ai metodi della classe.

Un modulo può essere incluso da più classi. I moduli non possono essere ereditati, ma questo modello "mixin" fornisce un tipo utile di "ereditarietà multipla". I puristi di OO non saranno d'accordo con questa affermazione, ma non lasciare che la purezza ostacoli il lavoro.


(Questa risposta era originariamente collegata http://www.rubycentral.com/pickaxe/classes.html, ma quel link e il suo dominio non sono più attivi.)


Sì, è così che funziona. Pertanto, i moduli non sono paragonabili alle classi "statiche" di Java; superclasse proxy (che alcuni chiamano un "metaclasse") diventa il destinatario di messaggi metodo di invio del modulo, il che rende è più simile a una classe statica in Java, ed i suoi metodi funzionano come metodi statici. Lo stesso vale, tuttavia, per le classi di Ruby, che possono assumere metodi "statici" inging extenduna classe. Ruby in realtà non distingue affatto tra i metodi "istanza" e "classe / statico", ma solo i loro ricevitori.
scottburton11,

7

Modulein Ruby, in una certa misura, corrisponde alla classe astratta di Java - ha metodi di istanza, le classi possono ereditarlo (tramite include, i ragazzi di Ruby lo chiamano "mixin"), ma non ha istanze. Ci sono altre differenze minori, ma queste informazioni sono sufficienti per iniziare.


6

namespace: i moduli sono namespace ... che non esistono in Java;)

Sono passato anche da Java e Python a Ruby, ricordo che aveva esattamente la stessa domanda ...

Quindi la risposta più semplice è che il modulo è uno spazio dei nomi, che non esiste in Java. In java la mentalità più vicina allo spazio dei nomi è un pacchetto .

Quindi un modulo in ruby ​​è come quello in java:
class? Nessuna
interfaccia? Nessuna
lezione astratta? Nessun
pacco?Sì forse)

metodi statici all'interno delle classi in java: uguale ai metodi all'interno dei moduli in ruby

In java l'unità minima è una classe, non puoi avere una funzione al di fuori di una classe. Tuttavia nel rubino questo è possibile (come il pitone).

Quindi cosa succede in un modulo?
classi, metodi, costanti. Il modulo li protegge in quello spazio dei nomi.

Nessuna istanza: i moduli non possono essere utilizzati per creare istanze

Insulti misti: a volte i modelli di ereditarietà non vanno bene per le classi, ma in termini di funzionalità vogliono raggruppare un insieme di classi / metodi / costanti

Regole sui moduli in ruby:
- I nomi dei moduli sono UpperCamelCase
- le costanti all'interno dei moduli sono TUTTE MAIUSCOLE (questa regola è la stessa per tutte le costanti ruby, non specifica per i moduli)
- Metodi di accesso: usare. operatore
costanti di accesso : utilizzare :: simbolo

semplice esempio di un modulo:

module MySampleModule
  CONST1 = "some constant"

  def self.method_one(arg1)
    arg1 + 2
  end
end

come usare i metodi all'interno di un modulo:

puts MySampleModule.method_one(1) # prints: 3

come usare le costanti di un modulo:

puts MySampleModule::CONST1 # prints: some constant

Alcune altre convenzioni sui moduli:
utilizzare un modulo in un file (come le classi ruby, una classe per file ruby)


“- metodi di accesso: uso. costanti di accesso operatore: usa :: simbolo ”solo questa risposta ha menzionato questo!
Qiulang,

4

In conclusione: un modulo è un incrocio tra una classe statica / di utilità e un mixin.

I mixin sono pezzi riutilizzabili di implementazione "parziale", che possono essere combinati (o composti) in modo mix & match, per aiutare a scrivere nuove classi. Naturalmente queste classi possono avere il proprio stato e / o codice.


1

Classe

Quando si definisce una classe, si definisce un modello per un tipo di dati. i dati di conservazione della classe, hanno un metodo che interagisce con tali dati e vengono utilizzati per creare un'istanza di oggetti.

Modulo

  • I moduli sono un modo per raggruppare metodi, classi e costanti.

  • I moduli offrono due vantaggi principali:

    => I moduli forniscono uno spazio dei nomi e prevengono gli scontri tra nomi. Lo spazio dei nomi aiuta a evitare conflitti con funzioni e classi con lo stesso nome che sono state scritte da qualcun altro.

    => I moduli implementano la funzione mixin.

(incluso il modulo in Klazz fornisce alle istanze di Klazz l'accesso ai metodi del modulo.)

(estendi Klazz con Mod dando alla classe Klazz l'accesso ai metodi Mods.)


0

Innanzitutto, alcune somiglianze che non sono ancora state menzionate. Ruby supporta le classi aperte, ma anche i moduli come aperti. Dopotutto, Class eredita da Module nella catena di ereditarietà di Class e quindi Class e Module hanno un comportamento simile.

Ma devi chiederti qual è lo scopo di avere sia una classe che un modulo in un linguaggio di programmazione? Una classe deve essere un modello per la creazione di istanze e ogni istanza è una variante realizzata del modello. Un'istanza è solo una variante realizzata di un progetto (la Classe). Naturalmente, quindi, le classi funzionano come creazione di oggetti. Inoltre, poiché a volte desideriamo che un progetto derivi da un altro modello, le classi sono progettate per supportare l'ereditarietà.

I moduli non possono essere istanziati, non creano oggetti e non supportano l'ereditarietà. Quindi ricorda che un modulo NON eredita da un altro!

Allora, qual è il punto di avere moduli in una lingua? Un ovvio utilizzo dei moduli è quello di creare uno spazio dei nomi, e lo noterai anche con altre lingue. Ancora una volta, il bello di Ruby è che i moduli possono essere riaperti (proprio come le classi). E questo è un grande uso quando si desidera riutilizzare uno spazio dei nomi in diversi file Ruby:

module Apple
  def a
    puts 'a'
  end
end

module Apple 
  def b
    puts 'b'
  end
end

class Fruit
  include Apple
end

 > f = Fruit.new
 => #<Fruit:0x007fe90c527c98> 
 > f.a
 => a
 > f.b
 => b

Ma non c'è ereditarietà tra i moduli:

module Apple
  module Green
    def green
      puts 'green'
    end
  end
end

class Fruit
  include Apple
end

> f = Fruit.new
 => #<Fruit:0x007fe90c462420> 
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>

Il modulo Apple non ha ereditato alcun metodo dal modulo Green e quando abbiamo incluso Apple nella classe Fruit, i metodi del modulo Apple vengono aggiunti alla catena di antenati delle istanze Apple, ma non i metodi del modulo Green, anche se il Green il modulo è stato definito nel modulo Apple.

Quindi, come possiamo accedere al metodo verde? Devi includerlo esplicitamente nella tua classe:

class Fruit
  include Apple::Green
end
 => Fruit 
 > f.green
=> green

Ma Ruby ha un altro uso importante per i moduli. Questa è la funzione Mixin, che descrivo in un'altra risposta su SO. Riassumendo, i mixin consentono di definire metodi nella catena di ereditarietà degli oggetti. Tramite i mixin, è possibile aggiungere metodi alla catena di ereditarietà delle istanze di oggetti (include) o alla classe_ singleton di self (estensione).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.