Ruby: Calling class method from instance
在Ruby中,如何从类的一个实例调用类方法?说我有
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
行
在实例方法中,您可以调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
输出:
1 2 | Class method: Foo Instance method: Foo |
在继承问题上,使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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" |
要访问实例方法内的类方法,请执行以下操作:
1 | self.class.default_make |
以下是解决您问题的另一种方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
现在让我们使用我们的类:
1 2 3 4 5 6 7 8 9 10 11 | t = Truck.new("Honda", 2000) t.make # =>"Honda" t.year # =>"2000" t = Truck.new t.make # =>"Toyota" t.year # => nil |
1 | self.class.default_make |
如果您有权访问委托方法,则可以执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 | [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 2 3 4 5 6 7 8 9 10 11 12 13 14 | [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" |
注意事项:
不要只是随机地删除cx1(3)所有不改变类和实例状态的内容,因为您将开始遇到奇怪的名称冲突问题。谨慎地做这件事,只有在你检查过之后,其他的东西才被压扁。
你做得对。类方法(类似于C++或Java中的"static"方法)不是实例的一部分,因此它们必须直接引用。
注意,在您的示例中,最好将"默认制作"作为常规方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/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() |
类方法对于使用类的实用程序类型函数更有用。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/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 |
再一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
下面是一个方法,介绍如何实现一个
发件人:你能在Ruby中的调用者上下文中评估代码吗?以及http://rubychallenger.blogspot.com.au/2011/07/caller-binding.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 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的补丁:)
与您的问题类似,您可以使用:
1 2 3 4 5 6 7 8 9 10 | class Truck def default_make # Do something end def initialize super self.default_make end end |