A modulok a Crystalben két célt szolgálnak:
Az első cél egy névtér létrehozása, hogy elkerüljük a névütközéseket. Emellett csoportosítja is a kódot, amitől könnyebb megérteni, hogy mire való.
A második cél az, hogy mixineket definiáljunk, amelyekkel a kódot típusok között oszthatjuk meg.
A modulok hasonlítanak az osztályokhoz, de a fő különbség az, hogy nem lehet őket példányosítani, így példányváltozóik sincsenek.
Egy modul deklarálásához a module kulcsszót használod, utána pedig a modul nevét írod.
module Foo
end
A névtér a kód csoportosításának egy módja.
Ezzel elkerülhetők a névütközések, és könnyebb megérteni, hogy mire való a kód.
Ha egy névtérbe helyezett konstanshoz vagy osztályhoz szeretnél hozzáférni, a :: operátort használod.
module Foo
class Bar
end
end
Foo::Bar.new
Ez akkor lehet hasznos, ha például több osztálynak ugyanarra az „alap” funkcionalitásra van szüksége, vagy ha a kódot nem rokon osztályok között kell megosztani. Vagy amikor olyan osztályok között szeretnénk megosztani a kódot, amelyek nem állnak kapcsolatban egymással.
Kétféleképpen használhatsz egy modult mixinként: az első az include kulcsszó használata, a második az extend kulcsszó használata.
Mindkettő elérhetővé teszi a modul konstansait annak a típusnak, amely a modult include-olja vagy extendeli.
Az include a modul összes metódusát példánymetódusként teszi elérhetővé azon a típuson, amelyik a modult include-olja.
Az include kulcsszót a típus elejére kell írni, utána pedig a modul nevét.
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
Az extend hasonlóan működik az include-hoz, de a metódusokat nem példánymetódusként, hanem osztálymetódusként teszi elérhetővé.
Az extend kulcsszót a típus elejére kell írni, utána pedig a modul nevét.
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
A Crystalben gyakori minta az, hogy egy modulban az extend self mintát használjuk.
Ezzel a modul összes metódusa osztálymetódusként lesz elérhető magán a modulon.
Ez azt jelenti, hogy nem kell minden metódust a def self.method_name szintaxissal a modulhoz rendelned.
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"