Ruby: Calling class method from instance

后端 未结 9 2038
谎友^
谎友^ 2021-01-29 17:26

In Ruby, how do you call a class method from one of that class\'s instances? Say I have

class Truck
  def self.default_make
    # Class method.
    \"mac\"
  end         


        
相关标签:
9条回答
  • 2021-01-29 18:19

    Using self.class.blah is NOT the same as using ClassName.blah when it comes to inheritance.

    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" 
    
    0 讨论(0)
  • 2021-01-29 18:23

    To access a class method inside a instance method, do the following:

    self.class.default_make
    

    Here is an alternative solution for your problem:

    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
    

    Now let's use our class:

    t = Truck.new("Honda", 2000)
    t.make
    # => "Honda"
    t.year
    # => "2000"
    
    t = Truck.new
    t.make
    # => "Toyota"
    t.year
    # => nil
    
    0 讨论(0)
  • Here's an approach on how you might implement a _class method that works as self.class for this situation. Note: Do not use this in production code, this is for interest-sake :)

    From: Can you eval code in the context of a caller in Ruby? and also 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
    

    Maybe the right answer is to submit a patch for Ruby :)

    0 讨论(0)
提交回复
热议问题