Lorsque je lisons plus sur les métaprogramming rubis, la plupart du temps, nous avons trouvé au moins deux solutions pour résoudre un problème. Veuillez regarder deux exemples ci-dessous:
module Base def self.included(klass) klass.extend ClassMethods end module ClassMethods def has_many(*args) # ... end end end class Student include Base has_many :books end
3 Réponses :
Vous avez beaucoup de théories autour de cette question. P>
J'ai tendance à préférer la composition car elle rend le comportement beaucoup plus réutilisable de cette façon, mais si vous regardez les rails, vous devrez faire sous-classe Activerecord :: classe de base à chaque fois que vous souhaitez un objet dans votre base de données. Si vous regardez Datamapper, c'est l'inverse car ils vous ont juste besoin d'inclure Datamapper :: Ressource. P>
L'héritage VS Composition (via des modules) est un gros sujet et la question que vous devrez vous poser de vous poser de la question suivante: comment puis-je obtenir le plus grand découplage entre les composants que je fournis et une autre base de code existante? p>
Ruby prend en charge un héritage unique uniquement. Par conséquent, si le client API doit hériter de votre classe de base, ils perdent la capacité d'hériter d'autres classes. Utilisation de l'inclusion du module Vous permettez à un code comme: et donc vous pouvez "hériter" à la fois personne et base. P> Cependant, la syntaxe de héritage classique semble plus naturelle et moins "magie" p> p>
Si votre API fournit la fonctionnalité de base qui sera étendue par le client, vous devriez préférer Si votre API va étendre divers clients avec leur propre fonctionnalité de base, vous devriez choisir une composition