Quelle est la différence entre les comprennent et s'étendent en Ruby?
Juste obtenir ma tête autour de Ruby métaprogrammation. Le mixin/modules arrivent toujours à me confondre.
- inclure: mélanges en module spécifié méthodes méthodes d'instance dans la classe cible
- étendre: mélanges en module spécifié méthodes les méthodes de la classe dans la classe cible
Est donc la différence majeure que ceci ou est un grand dragon tapi?
par exemple,
module ReusableModule
def module_method
puts "Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
puts "Include"
ClassThatIncludes.new.module_method # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method # "Module Method: Hi there!"
- Suivez ce lien aussi: juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby
Vous devez vous connecter pour publier un commentaire.
Ce que vous avez dit est correct. Cependant, il ya plus à lui que cela.
Si vous avez une classe
Klazz
et le moduleMod
, y comprisMod
dansKlazz
donne des instances deKlazz
accès àMod
's méthodes. Ou vous pouvez étendreKlazz
avecMod
donnant la classeKlazz
accès àMod
's méthodes. Mais aussi, vous pouvez étendre un objet arbitraire aveco.extend Mod
. Dans ce cas, la personne objet seMod
's méthodes, même si tous les autres objets de la même classe queo
ne le font pas.étendre - ajoute le module spécifié est des méthodes et des constantes de la cible métaclasse (c'est à dire la classe singleton)
par exemple,
Klazz.extend(Mod)
, maintenant Klazz a du Mod méthodes (comme les méthodes de la classe)obj.extend(Mod)
, maintenant obj a du Mod méthodes (comme les méthodes d'instance), mais aucune autre instance deobj.class
a ces méthodes ajoutées.extend
est une méthode publiqueinclure - Par défaut, il se mélange dans le module spécifié méthodes comme les méthodes d'instance dans la cible du module de classe.
par exemple,
class Klazz; include Mod; end;
, maintenant toutes les instances de Klazz avoir accès à du Mod méthodes (comme les méthodes d'instance)include
est une méthode privée, car il est destiné à être appelé à partir de la classe de conteneur/module.Cependant, des modules très souvent remplacer
include
le comportement de singe-patcher leincluded
méthode. Ceci est très important dans l'héritage des Rails de code. plus de détails à partir de Yehuda Katz.Plus de détails sur
include
, avec son comportement par défaut, en supposant que vous avez exécutez le code suivant@@foo
ou@@bar
super
dans Klazz#foo va vérifier pour les Mod#foo avant de vérifier à Klazz réel de la super-classe de la méthode foo. Voir la RubySpec pour les détails).Bien sûr, le rubis de la documentation de base est toujours le meilleur endroit où aller pour ces choses. Le RubySpec projet est également une ressource fantastique, car ils ont documenté la fonctionnalité précisément.
#include
RubySpec rubydoc#included
RubySpec rubydoc#extend
RubySpec rubydoc#extended
RubySpec rubydoc#extend_object
RubySpec rubydoc#append_features
RubySpec rubydocextend
peut appliquer les méthodes de la classe ou les méthodes d'instance, en fonction de l'utilisation.Klass.extend
= les méthodes de la classe,objekt.extend
= méthodes d'instance. J'ai toujours (à tort), a pris les méthodes de la classe est venu deextend
, et l'instance deinclude
.C'est correct.
Derrière les coulisses, est en fait un alias pour append_features, qui (à partir de la documentation):
Toutes les autres réponses sont bonnes, y compris la pointe de creuser à travers RubySpecs:
https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb
https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb
Comme pour les cas d'utilisation:
Si vous inclure module ReusableModule dans la classe ClassThatIncludes, les méthodes, les constantes, les classes, les submodules, et d'autres déclarations obtient référencés.
Si vous étendre classe ClassThatExtends avec le module ReusableModule, les méthodes et les constantes obtient copié. Évidemment, si vous n'êtes pas prudent, vous pouvez perdre beaucoup de mémoire dynamique de la duplication des définitions.
Si vous utilisons::Inquiétude, l' .inclus() fonctionnalité vous permet de réécrire l', y compris la classe directement. module ClassMethods à l'intérieur d'une Préoccupation obtient étendu (copié) dans l', y compris la classe.
Je tiens également à expliquer le mécanisme que l'on travaille. Si je ne suis pas de droite s'il vous plaît corriger.
Lorsque nous utilisons
include
nous sommes ajout d'un lien à partir de notre classe d'un module qui contient certaines méthodes.Objets n'ont pas de méthodes, seulement clases et les modules n'.
Alors, quand
a
reçoit mesagesome_method
il commence la méthode de recherchesome_method
dansa
's propres de la classe, puis dansA
classe, puis en liés àA
les modules de classe si il y en a (dans l'ordre inverse, dernière inclus victoires).Lorsque nous utilisons
extend
nous ajoutons un lien vers un module dans l'objet propre de la classe.Donc, si nous utilisons A. de nouveaux.étendre(MyMod) nous ajoutons un lien à notre module à Une instance propres la classe ou
a'
classe.Et si nous utilisons A. étendre(MyMod), nous ajoutons une liaison à Une(de l'objet, les classes sont aussi des objets) eigenclass
A'
.méthode de recherche de chemin pour
a
est comme suit:a => a' => les modules liés à une " classe => A.
il y a aussi un préfixe méthode qui change de chemin de recherche:
un => a' => précédées de modulesto Un => A => inclus un module à Un
désolé pour mon mauvais anglais.