operador modulos herencia clases ruby module

modulos - operador modulo en ruby



Extender un módulo de Ruby en otro módulo, incluidos los métodos del módulo (5)

Cada vez que trato de extender un módulo de ruby, pierdo los métodos del módulo. Ni incluir ni extender hará esto. Considera el fragmento:

module A def self.say_hi puts "hi" end end module B include A end B.say_hi #undefined_method

Ya sea que B incluya o extienda A, say_hi no estará definido.

¿Hay alguna manera de lograr algo como esto?


No creo que haya una forma simple de hacerlo.

Entonces, aquí hay una forma compleja:

module B class << self A.singleton_methods.each do |m| define_method m, A.method(m).to_proc end end end

Puedes ponerlo en un método de ayuda como este:

class Module def include_module_methods(mod) mod.singleton_methods.each do |m| (class << self; self; end).send :define_method, m, mod.method(m).to_proc end end end module B include_module_methods A end


Si usted es el autor del module A y lo necesitará con frecuencia, puede volver a crear A así:

module A module ClassMethods def say_hi puts "hi" end end extend ClassMethods def self.included( other ) other.extend( ClassMethods ) end end module B include A end A.say_hi #=> "hi" B.say_hi #=> "hi"


Use include_complete

gem install include_complete

module A def self.say_hi puts "hi" end end module B include_complete A end B.say_hi #=> "hi"


Johnathan, no estoy seguro si todavía te estás preguntando sobre esto, pero hay dos formas diferentes de usar módulos en ruby. A.) usa módulos en su forma autónoma Base :: Tree.entity (params) directamente en su código, o B.) usa módulos como mixins o métodos auxiliares.

A. Le permitirá usar módulos como un patrón de espacio de nombres. Esto es bueno para proyectos más grandes donde existe la posibilidad de conflictos de nombres de métodos

module Base module Tree def self.entity(params={},&block) # some great code goes here end end end

Ahora puede usar esto para crear algún tipo de estructura de árbol en su código, sin tener que instanciar una nueva clase para cada llamada a Base :: Tree.entity.

Otra forma de hacer Namespace-ing es en una clase por clase.

module Session module Live class Actor attr_accessor :type, :uuid, :name, :status def initialize(params={},&block) # check params, insert init values for vars..etc # save your callback as a class variable, and use it sometime later @block = block end def hit_rock_bottom end def has_hit_rock_bottom? end ... end end class Actor attr_accessor :id,:scope,:callback def initialize(params={},&block) self.callback = block if block_given? end def respond if self.callback.is_a? Proc # do some real crazy things... end end end end

Ahora tenemos el potencial de superposición en nuestras clases. Queremos saber que cuando creamos una clase Actor es la clase correcta, así que aquí es donde los espacios de nombres son útiles.

Session::Live::Actor.new(params) do |res|... Session::Actor.new(params)

B. Mix-Ins Estos son tus amigos. Úselos cada vez que crea que tendrá que hacer algo más de una vez en su código.

module Friendly module Formatter def to_hash(xmlstring) #parsing methods return hash end def remove_trailing_whitespace(string,&block) # remove trailing white space from that idiot who pasted from textmate end end end

Ahora, cada vez que necesite formatear un xmlstring como un hash, o eliminar los espacios en blanco al final en cualquiera de sus códigos futuros, simplemente mezcle.

module Fun class Ruby include Friendly::Formatter attr_accessor :string def initialize(params={}) end end end

Ahora puedes formatear la cadena en tu clase.

fun_ruby = Fun::Ruby.new(params) fun_ruby.string = "<xml><why><do>most</do><people></people><use>this</use><it>sucks</it></why></xml>" fun_ruby_hash = fun_ruby.to_hash(fun_ruby.string)

Espero que esta sea una buena explicación. Los puntos planteados anteriormente son buenos ejemplos de formas de extender clases, pero con los módulos, la parte difícil es cuándo usar la palabra clave self . Se refiere al alcance del objeto dentro de la jerarquía de objetos de ruby. Entonces, si desea usar un módulo como mezcla y no desea declarar nada solo, no use la palabra clave auto, sin embargo, si desea mantener el estado dentro del objeto, simplemente use una clase y mezcle. en los módulos que quieras.


No me gusta que todos usen self.included . Tengo una solución más simple:

module A module ClassMethods def a ''a1'' end end def a ''a2'' end end module B include A module ClassMethods include A::ClassMethods def b ''b1'' end end def b ''b2'' end end class C include B extend B::ClassMethods end class D < C; end puts D.a puts D.b puts D.new.a puts D.new.b