首页 文章

Ruby:从实例调用类方法

提问于
浏览
299

在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 ?好像应该有 .

9 回答

  • 1

    如果您有权访问委托方法,则可以执行以下操作:

    [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 所有不会开始遇到奇怪的名称冲突问题 . 谨慎地这样做,只有在你检查后没有其他东西被压扁 .

  • 6
    self.class.default_make
    
  • 496

    你是以正确的方式做到的 . 类方法(类似于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()
    

    类方法对于使用该类的实用程序类型函数更有用 . 例如:

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

    多一个:

    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
    
  • 6

    与您的问题类似,您可以使用:

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

    在实例方法中,您可以只调用 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
    

    输出:

    Class method: Foo
    Instance method: Foo
    
  • -6

    使用 self.class.blah 与继承时使用 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"
    
  • 164

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

    self.class.default_make
    

    以下是您的问题的替代解决方案:

    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
    
  • 2

    这是一种关于如何实现 _class 方法的方法,该方法在这种情况下用作 self.class . 注意:不要在 生产环境 代码中使用它,这是为了感兴趣:)

    来自:Can you eval code in the context of a caller in 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提交补丁:)

相关问题