On m'a posé une question aujourd'hui: "Comment définir une méthode statique dans un module et l'inclure dans une classe ?". Simple non ?!
Justement j'avais eu le même problème quand j'avais fait mon projet "natural_sort"
Justement j'avais eu le même problème quand j'avais fait mon projet "natural_sort"
Spontanément j'ai essayé:
module Carnivore
def self.manger(oiseau)
puts "slurp! #{oiseau}"
end
end
class GrosMinet
include Carnivore
end
Carnivore.manger "titi" # ok ca foncionnne
GrosMinet.manger "titi" # undefined method `manger' for GrosMinet:Class (NoMethodError) WTF ?!
Malheureusement ça ne fonctionne pas :(
Dans NaturalSort, j'ai contourné le problème:
Dans NaturalSort, j'ai contourné le problème:
module NaturalSort
def self.naturalsort(object)
...
end
def natural_sort
NaturalSort::naturalsort(to_a)
end
end
Je suis tombé sur cet article: "Ruby Mixin Tutorial" et j'ai essayé différentes combinaisons, il n'y en pas une qui soit satifaisante dans tous les cas...
Ici vous pourrez voir les principales étapes jusqu'à la version finale, celle qui me satisfait le plus.
Ici vous pourrez voir les principales étapes jusqu'à la version finale, celle qui me satisfait le plus.
Etape n°1: classe statique dans le module uniquement
module Carnivore
def self.manger(oiseau)
puts "slurp! #{oiseau}"
end
end
Carnivore.manger "titi"
Etape n°2: méthode d'instance de classe (l'utilisation classique du module par excellence):
module Carnivore
def manger(oiseau)
puts "slurp! #{oiseau}"
end
end
class GrosMinet
include Carnivore
end
gros_minet = GrosMinet.new
gros_minet.manger "titi"
Version finale. 2 grosses subtilités:
- il n'y a pas de 'self' dans la définition de la méthode 'manger'
- On utilise 'extends' au lieu de 'include'
module Carnivore
def manger(oiseau)
puts "slurp! #{oiseau}"
end
end
module Chat
def miauler
puts "miaou..."
end
end
class GrosMinet
include Chat
# include Carnivore # necessaire à gros_minet.manger("titi")
extend Carnivore
end
GrosMinet.manger "titi"
gros_minet = GrosMinet.new
gros_minet.miauler
# gros_minet.manger "titi" # necessite le include Carnivore pour fonctionner
Conclusion: Ca fonctionne et le code est court mais je trouve la syntax un peut étrange, je ne comprend pas trop pourquoi le 'include' n'inclus pas les méthodes 'self' ? il y a quelquechose qui m'échappe pour l'instant...
Du coup je pense que c'est une bonne pratique de ne pas utiliser de méthodes préfixé par 'self' dans le modules et que faire MonModule.ma_methode n'est peut-être pas très orienté objet... après tout les modules ne sont pas vraiment des objets et ne devraient pas être utilisés seuls ? Qu'est ce que vous en pensez ?
1 commentaire:
Je crois surtout qu'il ne faut pas chercher à utiliser les méthodes statique comme dans le monde Java par exemple.
Dans ruby, l'utilisation de méthode statique dans un module ne me choque pas, c'est juste qu'il faut avoir à l'esprit que c'est une méthode propre au module (puisque statique) et donc non partagé par l'instance d'un objet l'incluant, mais disponible uniquement par l'instance du Module directement.
Enfin bref. Si c'est possible, il y a surement un interêt :)
Enregistrer un commentaire