Modules

L'utilisation de modules a deux objectifs:

  • comme espace de nom pour définir d'autres types, méthodes et constantes,
  • comme types partiels qui peuvent être inclus dans d'autres types.

Un exemple de module comme espace de nom:

module Curses
  class Window
  end
end

Curses::Window.new

Les auteurs de librairies sont encouragés à mettre leurs définitions dans des modules pour éviter les collisions de nommage. La librairie standard n'a généralement pas d'espace de nom étant donné que ses types et méthodes sont très communs, afin d'éviter d'écrire des noms longs.

Pour utiliser un module comme type partiel on utilise include ou extend.

Un include fait qu'un type inclut des méthodes définies dans un module comme méthodes d'instance:

module ItemsSize
  def size
    items.size
  end
end

class Items
  include ItemsSize

  def items
    [1, 2, 3]
  end
end

items = Items.new
items.size #=> 3

Dans l'espace précédent, c'est comme si l'on avait copié-collé la méthode size du module dans la classe Items. Cela marche en réalité du fait que chaque type a une liste d'ancêtres, ou parents. Par défaut cette liste débute avec la super classe. Au fur et à mesure de leur inclusion, les modules sont ajoutés en tête de cette liste. Quand une méthode n'est pas trouvée dans un type, elle est recherchée dans cette liste. À l'invocation de super, le premier type de cette liste d'ancêtres est utilisé.

Un module peut inclure d'autres modules, ainsi si une méthode n'est pas trouvée dans un module elle sera recherchée dans les modules inclus.

Un extend fait qu'un type inclut des méthodes définies dans un module comme méthodes de classe:

module SomeSize
  def size
    3
  end
end

class Items
  extend SomeSize
end

Items.size #=> 3

include comme extend rendent les constantes définies dans un module disponible au type inclus/étendu.

Les deux peuvent être utilisées en tête, pour éviter d'avoir à écrire un espace de nom encore et encore (bien que les chances de collision de nommage augmentent):

module SomeModule
  class SomeType
  end

  def some_method
    1
  end
end

include SomeModule

SomeType.new # OK, same as SomeModule::SomeType
some_method  # OK, 1

extend self

Un modèle commun des modules est extend self:

module Base64
  extend self

  def encode64(string)
    # ...
  end

  def decode64(string)
    # ...
  end
end

De cette manière un module peut être utilisé comme espace de nom:

Base64.encode64 "hello" #=> "aGVsbG8="

Mais il peut aussi être inclus dans le programme et ses méthodes peuvent être invoquées sans espace de nom:

include Base64

encode64 "hello" #=> "aGVsbG8="

Pour que cela soit utile le nom de la méthode doit présenter un lien avec le module, sinon les chances de collision de nom sont élevées.

Un module ne peut être instancié:

module Moo
end

Moo.new # undefined method 'new' for Moo:Class

results matching ""

    No results matching ""