Ruby:从实例调用类方法

在Ruby中,如何从该类的实例中调用一个类方法? 说我有

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 

Truck.default_make检索默认。 但是有没有提到这个,而不提卡Truck ? 似乎应该有。

而不是引用类的字面名称,在一个实例方法内,你可以调用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 

输出:

类方法:Foo
实例方法:Foo

在使用self.class.blah时,与inheritance时使用ClassName.blah

 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 

要访问实例方法内的类方法,请执行以下操作:

 self.class.default_make 

这是您的问题的替代解决scheme:

 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 

现在我们来使用我们的类:

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

你做的是正确的。 类方法(类似于C ++或Java中的“静态”方法)不是实例的一部分,所以它们必须直接引用。

在这个说明中,在你的例子中,你最好使'default_make'成为一个常规的方法:

 #!/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() 

类方法对使用类的实用types函数更有用。 例如:

 #!/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 

如果你有权访问委托方法,你可以这样做:

 [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" 

或者,也许更干净,如果你有更多的方法或两个你想委派到类和实例:

 [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" 

谨慎的一句话:

不要随便delegate不改变状态的所有东西都delegate给类和实例,因为你会开始遇到奇怪的名字冲突问题。 做这个节约,只有在你没有检查任何东西被压扁。

多一个:

 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 

这里有一个关于如何实现一个用作self.class_class方法的方法。 注意:不要在生产代码中使用这个,这是为了感兴趣:)

来自: 你可以在Ruby调用者的上下文中评估代码吗? 还有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 

也许正确的答案是为Ruby提交补丁:)

类似你的问题,你可以使用:

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