Kurz: Ein Modul ist eine Sammlung von Methoden und Konstanten. Es dient als Namensraum und als Mixin (Code in Klassen einmischen). Module lassen sich nicht instanziieren.
Teil des Kurses Ruby
Module
Ein Modul ist eine Sammlung von Methoden und Konstanten. Es dient als Namensraum und als Mixin (Code in Klassen einmischen). Module lassen sich nicht instanziieren.
module Geometrie
PI = 3.14159
def self.kreisflaeche(r) = PI * r * r
class Kreis
def initialize(r) = @r = r
def flaeche = Geometrie.kreisflaeche(@r)
end
end
puts Geometrie.kreisflaeche(2)
puts Geometrie::Kreis.new(1).flaeche
puts Geometrie::PIAusgabe:
12.56636
3.14159
3.14159Mixins mit include
module Begruessung
def hallo = "Hallo, ich bin #{name}"
end
module Laufend
def laufe = "#{name} läuft"
end
class Mensch
include Begruessung, Laufend
attr_reader :name
def initialize(name) = @name = name
end
m = Mensch.new("Mia")
puts m.hallo, m.laufe
p Mensch.ancestors.first(4), m.is_a?(Begruessung)Ausgabe:
Hallo, ich bin Mia
Mia läuft
[Mensch, Begruessung, Laufend, Object]
trueinclude macht Modulmethoden zu Instanzmethoden, extend zu Klassenmethoden, prepend setzt das Modul vor die Klasse.
module Zaehler
def zaehle = @n = (@n || 0) + 1
end
module Info
def info = "Klasse #{name}"
end
module Laut
def sprich = super.upcase
end
class Robot
include Zaehler
extend Info
prepend Laut
def sprich = "piep"
end
r = Robot.new
r.zaehle
puts r.zaehle, Robot.info, r.sprichAusgabe:
2
Klasse Robot
PIEPComparable und Enumerable
Zwei eingebaute Module machen eigene Klassen mächtig: Wer <=> definiert und Comparable einbindet, bekommt <, >, between?, clamp. Wer each definiert und Enumerable einbindet, bekommt map, select, sort, min, sum, first, include? … geschenkt:
class Regal
include Enumerable
def initialize(*buecher) = @buecher = buecher
def each(&block)
return to_enum(:each) unless block
@buecher.each(&block)
self
end
end
r = Regal.new("Faust", "Emil", "Momo", "Ronja")
p r.sort, r.map(&:length), r.select { |b| b.length == 4 }, r.min_by(&:length), r.first(2)
p r.include?("Momo"), r.each_slice(2).to_a, r.sum(&:length), r.to_a.last, r.each_with_index.to_a.first
p r.lazy.map(&:upcase).first(2), r.reduce { |a, b| a.length > b.length ? a : b }Ausgabe:
["Emil", "Faust", "Momo", "Ronja"]
[5, 4, 4, 5]
["Emil", "Momo"]
"Emil"
["Faust", "Emil"]
true
[["Faust", "Emil"], ["Momo", "Ronja"]]
18
"Ronja"
["Faust", 0]
["FAUST", "EMIL"]
"Ronja"Eigene Iteratoren und Enumeratoren
class Fibonacci
include Enumerable
def each
a, b = 0, 1
loop do
yield a
a, b = b, a + b
end
end
end
p Fibonacci.new.lazy.select(&:even?).first(5)
p Fibonacci.new.take(10)
zaehler = Enumerator.new do |y|
n = 0
loop { y << (n += 1) }
end
p zaehler.take(3), zaehler.next, zaehler.next, zaehler.peekAusgabe:
[0, 2, 8, 34, 144]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
[1, 2, 3]
1
2
3Merke
- Module sind Namensräume und Mixins;
include,extend,prepend - Vererbungsreihenfolge siehst du mit
ancestors Comparable(mit<=>) undEnumerable(miteach) liefern viele Methoden gratisEnumeratorundlazyfür unendliche Folgen
Übungsaufgabe
Baue eine Klasse Playlist, die Enumerable einbindet und eine Methode gesamtdauer anbietet.
Quiz zur Selbstkontrolle
Was liefert include Modul in einer Klasse?
- Die Modulmethoden werden zu Instanzmethoden (richtig)
- Die Modulmethoden werden zu Klassenmethoden
- Nichts
- Eine Vererbung
Welche Methode musst du für Enumerable definieren?
- each (richtig)
- map
- <=>
- to_a
Wofür ist <=> wichtig?
- Für Vergleiche und Sortierung (Comparable) (richtig)
- Für Zuweisungen
- Für Strings
- Für Hashes
Weiter im Kurs
Zurück: Klassen und Objekte
Weiter: Fehlerbehandlung, Dateien und JSON
Alle Kapitel: Ruby im Überblick