Unterschied zwischen einer Klasse und einem Modul

437

Ich komme aus Java und arbeite jetzt mehr mit Ruby.

Eine Sprachfunktion, mit der ich nicht vertraut bin, ist die module. Ich frage mich, was genau ein ist moduleund wann Sie einen verwenden und warum Sie einen moduleüber einen verwenden class.

Josh Moore
quelle

Antworten:

398

Die erste Antwort ist gut und gibt einige strukturelle Antworten, aber ein anderer Ansatz besteht darin, darüber nachzudenken, was Sie tun. Bei Modulen geht es darum, Methoden bereitzustellen, die Sie für mehrere Klassen verwenden können. Stellen Sie sich diese als "Bibliotheken" vor (wie Sie es in einer Rails-App sehen würden). Klassen handeln von Objekten; Module sind über Funktionen.

Beispielsweise sind Authentifizierungs- und Autorisierungssysteme gute Beispiele für Module. Authentifizierungssysteme funktionieren über mehrere Klassen auf App-Ebene (Benutzer werden authentifiziert, Sitzungen verwalten die Authentifizierung, viele andere Klassen verhalten sich je nach Authentifizierungsstatus unterschiedlich), sodass Authentifizierungssysteme als gemeinsam genutzte APIs fungieren.

Sie können ein Modul auch verwenden, wenn Sie Methoden für mehrere Apps gemeinsam genutzt haben (auch hier ist das Bibliotheksmodell gut).

scottru
quelle
7
Entspricht das Modul den Schnittstellen in Java?
Saad Rehman Shah
14
@Caffeine nicht wirklich, weil Ruby-Module tatsächlich Implementierungen enthalten, während Schnittstellen in Java abstrakt sind
Jorge Israel Peña
8
Nein, Module und Java-Pakete / JARs sind völlig unterschiedliche Tiere.
Karoly Horvath
9
Ich bin eher wie abstrakte Klassen mit Methodenimplementierung.
Automatico
2
Tatsächlich trifft @Chole auf eines der schönen Dinge an Modulen: Namespacing. Während Module kein direktes Äquivalent zu Paketen in Java sind, können sie verwendet werden, um etwas Ähnliches zu erreichen: 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Sergii Shevchyk
quelle
Was ist die Oberklasse der Klasse?
Aashish P
10
Ich habe die Hierarchie Klasse -> Modul -> Objekt -> BasicObject. Cool!!
Aashish P
Warum besteht "Modul besteht aus" Auslassungsvariablen, wenn sowohl Klassen als auch Module Klassenvariablen unterstützen? Siehe akzeptierte Antwort auf stackoverflow.com/questions/5690458/…
kaleidic
Viele Diagramme in all diesen Antworten. Ein kleines laufendes Beispiel: rubyfiddle.com/riddles/06081
Donato
16
Wie kann ein Modul "nicht instanziiert" werden und dennoch Instanzmethoden haben?
Devius
91

Ich bin überrascht, dass dies noch niemand gesagt hat.

Da der Fragesteller aus Java stammt (und ich auch), ist hier eine Analogie, die hilft.

Klassen sind einfach wie Java-Klassen.

Module sind wie statische Java-Klassen. Denken Sie an den MathUnterricht in Java. Sie instanziieren es nicht und verwenden die Methoden in der statischen Klasse (z. B. Math.random()) wieder.

Linan
quelle
11
Module können der Include-Klasse jedoch auch Instanzmethoden hinzufügen, statische Klassen in Java jedoch nicht.
Stellen Sie Monica wieder her - notmaynard
4
Diese Aussage trifft auch auf einen starken C # -Hintergrund zu.
Damon Drake
5
Das ist nicht ganz richtig; Module haben keine statischen Methoden, sie haben nur Methoden. Module können sich "erweitern" (die Syntax ist tatsächlich extend self) und ihre Methoden für die selfMetaklasse ihres Benutzers verfügbar machen . Dies ermöglicht den Versand einer Methode wie random()auf einem MathModul. Die Methoden eines Moduls können jedoch naturgemäß nicht allein aufgerufen werden self. Dies hat mit Rubys Vorstellung von self, seinen Metaklassen und der Funktionsweise der Methodensuche zu tun . Weitere Informationen finden Sie unter "Metaprogramming Ruby" - Paolo Perlotta.
Scottburton11
Ich würde sagen, dass Module Schnittstellen mit Methoden in ihnen ähnlicher sind (Java 8-Schnittstellen mit Standardimplikation), aber im Gegensatz zu Java-Schnittstellen nicht voneinander erben können
dividierenByZero
Wie diese Antwort hat so viele Stimmen? Übrigens, das wurde in besseren Worten 1 Monat zuvor gesagt: stackoverflow.com/a/17027346/986862
Andre Figueiredo
39

Grundsätzlich kann das Modul nicht instanziiert werden. Wenn eine Klasse ein Modul enthält, wird eine Proxy-Superklasse generiert, die Zugriff auf alle Modulmethoden sowie die Klassenmethoden bietet.

Ein Modul kann von mehreren Klassen eingeschlossen werden. Module können nicht vererbt werden, aber dieses "Mixin" -Modell bietet eine nützliche Art der "Mehrfachvererbung". OO-Puristen werden dieser Aussage nicht zustimmen, aber lassen Sie nicht zu, dass Reinheit die Arbeit behindert.


(Diese Antwort war ursprünglich verlinkt http://www.rubycentral.com/pickaxe/classes.html, aber dieser Link und seine Domain sind nicht mehr aktiv.)

Hurcane
quelle
Ja, so funktioniert es. Daher sind Module nicht mit den "statischen" Klassen von Java vergleichbar. Die Proxy-Superklasse (manche nennen sie eine "Metaklasse") wird zum Empfänger der Methodenversandnachrichten des Moduls, wodurch sie mit einer statischen Klasse in Java vergleichbarer wird und ihre Methoden wie statische Methoden funktionieren. Gleiches gilt jedoch für Rubys Klassen, die durch extendeine Klasse "statische" Methoden annehmen können . Ruby unterscheidet eigentlich überhaupt nicht zwischen "Instanz" - und "Klasse / Statik" -Methoden, sondern nur zwischen deren Empfängern.
Scottburton11
7

Modulein Ruby entspricht bis zu einem gewissen Grad der abstrakten Java- Klasse - hat Instanzmethoden, Klassen können davon erben (via include, Ruby-Leute nennen es ein "Mixin"), hat aber keine Instanzen. Es gibt noch andere kleine Unterschiede, aber so viele Informationen reichen aus, um Ihnen den Einstieg zu erleichtern.

Boris Stitnicky
quelle
6

Namespace: Module sind Namespaces ... die in Java nicht existieren;)

Ich habe auch von Java und Python zu Ruby gewechselt, ich erinnere mich, dass ich genau die gleiche Frage hatte ...

Die einfachste Antwort ist also, dass das Modul ein Namespace ist, der in Java nicht existiert. In Java ist die dem Namespace am nächsten liegende Denkweise ein Paket .

Ein Modul in Ruby ist also wie in Java:
Klasse? Keine
Schnittstelle? Keine
abstrakte Klasse? Kein
Paket? Ja vielleicht)

statische Methoden in Klassen in Java: wie Methoden in Modulen in Ruby

In Java ist die Mindesteinheit eine Klasse. Sie können keine Funktion außerhalb einer Klasse haben. Bei Ruby ist dies jedoch möglich (wie bei Python).

Was steckt also in einem Modul?
Klassen, Methoden, Konstanten. Das Modul schützt sie unter diesem Namespace.

Keine Instanz: Module können nicht zum Erstellen von Instanzen verwendet werden

Gemischte Ins: Manchmal sind Vererbungsmodelle nicht gut für Klassen, aber in Bezug auf die Funktionalität möchten Sie eine Reihe von Klassen / Methoden / Konstanten zusammenfassen

Regeln für Module in Ruby:
- Modulnamen sind UpperCamelCase
- Konstanten innerhalb von Modulen sind ALL CAPS (diese Regel ist für alle Ruby-Konstanten gleich, nicht modulspezifisch )
- Zugriffsmethoden: use. Operator
- Zugriffskonstanten: use :: symbol

einfaches Beispiel eines Moduls:

module MySampleModule
  CONST1 = "some constant"

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

Verwendung von Methoden innerhalb eines Moduls:

puts MySampleModule.method_one(1) # prints: 3

Verwendung von Konstanten eines Moduls:

puts MySampleModule::CONST1 # prints: some constant

Einige andere Konventionen zu Modulen:
Verwenden Sie ein Modul in einer Datei (z. B. Ruby-Klassen, eine Klasse pro Ruby-Datei).

Apadana
quelle
“- Zugriffsmethoden: verwenden. Operator - Zugriffskonstanten: use :: symbol ”Nur diese Antwort erwähnte dies!
Qiulang
4

Fazit: Ein Modul ist eine Kreuzung zwischen einer statischen / Utility-Klasse und einem Mixin.

Mixins sind wiederverwendbare Teile einer "teilweisen" Implementierung, die in Mix & Match-Weise kombiniert (oder komponiert) werden können, um das Schreiben neuer Klassen zu erleichtern. Diese Klassen können natürlich zusätzlich einen eigenen Status und / oder Code haben.

IQ sagte
quelle
1

Klasse

Wenn Sie eine Klasse definieren, definieren Sie einen Entwurf für einen Datentyp. Klasse hält Daten, verfügt über Methoden, die mit diesen Daten interagieren und zum Instanziieren von Objekten verwendet werden.

Modul

  • Module sind eine Möglichkeit, Methoden, Klassen und Konstanten zu gruppieren.

  • Module bieten Ihnen zwei Hauptvorteile:

    => Module bieten einen Namespace und verhindern Namenskonflikte. Mithilfe des Namespace können Konflikte mit Funktionen und Klassen mit demselben Namen vermieden werden, die von einer anderen Person geschrieben wurden.

    => Module implementieren die Mixin-Funktion.

(einschließlich Modul in Klazz ermöglicht Instanzen von Klazz den Zugriff auf Modulmethoden.)

(Erweitern Sie Klazz mit Mod und geben Sie der Klasse Klazz Zugriff auf Mods-Methoden.)

Prasanthrubyist
quelle
0

Zunächst einige Ähnlichkeiten, die noch nicht erwähnt wurden. Ruby unterstützt offene Klassen, aber auch offene Module. Schließlich erbt Class von Module in der Class-Vererbungskette, sodass Class und Module ein ähnliches Verhalten aufweisen.

Aber Sie müssen sich fragen, was der Zweck ist, sowohl eine Klasse als auch ein Modul in einer Programmiersprache zu haben? Eine Klasse soll eine Blaupause zum Erstellen von Instanzen sein, und jede Instanz ist eine realisierte Variation der Blaupause. Eine Instanz ist nur eine realisierte Variation einer Blaupause (der Klasse). Klassen fungieren dann natürlich als Objekterstellung. Da wir manchmal möchten, dass eine Blaupause von einer anderen Blaupause abgeleitet wird, sind Klassen so konzipiert, dass sie die Vererbung unterstützen.

Module können nicht instanziiert werden, erstellen keine Objekte und unterstützen keine Vererbung. Denken Sie also daran, dass ein Modul NICHT von einem anderen erbt!

Was bringt es dann, Module in einer Sprache zu haben? Eine offensichtliche Verwendung von Modulen besteht darin, einen Namespace zu erstellen, und Sie werden dies auch bei anderen Sprachen bemerken. Wiederum ist das Coole an Ruby, dass Module wieder geöffnet werden können (genau wie Klassen). Dies ist eine große Verwendung, wenn Sie einen Namespace in verschiedenen Ruby-Dateien wiederverwenden möchten:

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

Es gibt jedoch keine Vererbung zwischen Modulen:

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>

Das Apple-Modul hat keine Methoden vom Green-Modul geerbt. Wenn wir Apple in die Fruit-Klasse aufgenommen haben, werden die Methoden des Apple-Moduls zur Ahnenkette der Apple-Instanzen hinzugefügt, nicht jedoch die Methoden des Green-Moduls, obwohl das Green-Modul Modul wurde im Apple-Modul definiert.

Wie erhalten wir Zugang zur grünen Methode? Sie müssen es explizit in Ihre Klasse aufnehmen:

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

Aber Ruby hat eine andere wichtige Verwendung für Module. Dies ist die Mixin-Funktion, die ich in einer anderen Antwort auf SO beschreibe. Zusammenfassend lässt sich sagen, dass Sie mit Mixins Methoden in die Vererbungskette von Objekten definieren können. Über Mixins können Sie Methoden zur Vererbungskette von Objektinstanzen (include) oder zur singleton_class von self (extens) hinzufügen.

Donato
quelle