orientado objetos ruby class-method

objetos - modulo ruby



Ruby: método de clase de llamada de instancia (9)

En lugar de referirse al nombre literal de la clase, dentro de un método de instancia, puede simplemente llamar self.class.whatever .

class Foo def self.some_class_method puts self end def some_instance_method self.class.some_class_method end end print "Class method: " Foo.some_class_method print "Instance method: " Foo.new.some_instance_method

Salidas:

Class method: Foo Instance method: Foo

En Ruby, ¿cómo llamas a un método de clase desde una de las instancias de esa clase? Di que tengo

class Truck def self.default_make # Class method. "mac" end def initialize # Instance method. Truck.default_make # gets the default via the class''s method. # But: I wish to avoid mentioning Truck. Seems I''m repeating myself. end end

La línea Truck.default_make recupera el valor predeterminado. ¿Pero hay una manera de decir esto sin mencionar a Truck ? Parece que debería haber.


Este es un enfoque sobre cómo podría implementar un método _class que funcione como self.class para esta situación. Nota: No use esto en el código de producción, esto es por interés :)

De: ¿Puede evaluar el código en el contexto de una persona que llama en Ruby? y también http://rubychallenger.blogspot.com.au/2011/07/caller-binding.html

# Rabid monkey-patch for Object require ''continuation'' if RUBY_VERSION >= ''1.9.0'' class Object def __; eval ''self.class'', caller_binding; end alias :_class :__ def caller_binding cc = nil; count = 0 set_trace_func lambda { |event, file, lineno, id, binding, klass| if count == 2 set_trace_func nil cc.call binding elsif event == "return" count += 1 end } return callcc { |cont| cc = cont } end end # Now we have awesome def Tiger def roar # self.class.roar __.roar # or, even _class.roar end def self.roar # TODO: tigerness end end

Tal vez la respuesta correcta es enviar un parche para Ruby :)


Lo estás haciendo de la manera correcta. Los métodos de clase (similares a los métodos ''estáticos'' en C ++ o Java) no forman parte de la instancia, por lo que deben ser referenciados directamente.

En esa nota, en su ejemplo, sería mejor utilizar el método ''default_make'' como un método regular:

#!/usr/bin/ruby class Truck def default_make # Class method. "mac" end def initialize # Instance method. puts default_make # gets the default via the class''s method. end end myTruck = Truck.new()

Los métodos de clase son más útiles para las funciones de tipo utilidad que usan la clase. Por ejemplo:

#!/usr/bin/ruby class Truck attr_accessor :make def default_make # Class method. "mac" end def self.buildTrucks(make, count) truckArray = [] (1..count).each do truckArray << Truck.new(make) end return truckArray end def initialize(make = nil) if( make == nil ) @make = default_make() else @make = make end end end myTrucks = Truck.buildTrucks("Yotota", 4) myTrucks.each do |truck| puts truck.make end


Para acceder a un método de clase dentro de un método de instancia, haga lo siguiente:

self.class.default_make

Aquí hay una solución alternativa para su problema:

class Truck attr_accessor :make, :year def self.default_make "Toyota" end def make @make || self.class.default_make end def initialize(make=nil, year=nil) self.year, self.make = year, make end end

Ahora vamos a usar nuestra clase:

t = Truck.new("Honda", 2000) t.make # => "Honda" t.year # => "2000" t = Truck.new t.make # => "Toyota" t.year # => nil


Si tiene acceso al método de delegado, puede hacer esto:

[20] pry(main)> class Foo [20] pry(main)* def self.bar [20] pry(main)* "foo bar" [20] pry(main)* end [20] pry(main)* delegate :bar, to: ''self.class'' [20] pry(main)* end => [:bar] [21] pry(main)> Foo.new.bar => "foo bar" [22] pry(main)> Foo.bar => "foo bar"

Alternativamente, y probablemente más limpio si tiene más de un método o dos que desea delegar a la clase y la instancia:

[1] pry(main)> class Foo [1] pry(main)* module AvailableToClassAndInstance [1] pry(main)* def bar [1] pry(main)* "foo bar" [1] pry(main)* end [1] pry(main)* end [1] pry(main)* include AvailableToClassAndInstance [1] pry(main)* extend AvailableToClassAndInstance [1] pry(main)* end => Foo [2] pry(main)> Foo.new.bar => "foo bar" [3] pry(main)> Foo.bar => "foo bar"

Una palabra de precaución:

No solo delegate aleatoriamente todo lo que no cambie de estado a clase e instancia, ya que comenzará a tener problemas de conflictos de nombres extraños. Haz esto con moderación y solo después de que hayas verificado nada más será aplastado.


Similar a tu pregunta, podrías usar:

class Truck def default_make # Do something end def initialize super self.default_make end end


Uno mas:

class Truck def self.default_make "mac" end attr_reader :make private define_method :default_make, &method(:default_make) def initialize(make = default_make) @make = make end end puts Truck.new.make # => mac


Usar self.class.blah NO es lo mismo que usar ClassName.blah cuando se trata de herencia.

class Truck def self.default_make "mac" end def make1 self.class.default_make end def make2 Truck.default_make end end class BigTruck < Truck def self.default_make "bigmac" end end ruby-1.9.3-p0 :021 > b=BigTruck.new => #<BigTruck:0x0000000307f348> ruby-1.9.3-p0 :022 > b.make1 => "bigmac" ruby-1.9.3-p0 :023 > b.make2 => "mac"


self.class.default_make