Ruby:从实例调用类方法

Pet*_*ter 331 ruby class-method

在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
Run Code Online (Sandbox Code Playgroud)

该行Truck.default_make检索默认值.但有没有提到这样说的方法Truck呢?好像应该有.

Mar*_*off 540

您可以调用实例方法,而不是引用类的文字名称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
Run Code Online (Sandbox Code Playgroud)

输出:

Class method: Foo
Instance method: Foo

  • @MattConnolly,同样使用`self.class`,如果碰巧重命名该类,则无需搜索/替换. (28认同)
  • @MattConnolly,它是相对的,如果你的类名是`SalesforceSyncJob`那么它更短;) (21认同)
  • @GusShortz是的.另外,如果有子类,self.class会更好. (8认同)
  • 我想在ruby中看到一些从实例调用类方法的快捷方式.即:> some_class_method而不是self.class.some_class_method (7认同)
  • 虽然这是正确的答案,但遗憾的是"self.class"比类名"Truck"更容易打字并且不易阅读.那好吧.... (7认同)

小智 180

使用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" 
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是对已接受答案的回应,而不是对问题的回答. (57认同)
  • @zohn - 是的,但在考虑使用什么时,这仍然是有用的上下文. (15认同)
  • @MattSanders 在这些情况下只使用评论。 (3认同)

Har*_*tty 13

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

self.class.default_make
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

现在让我们使用我们的课程:

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

t = Truck.new
t.make
# => "Toyota"
t.year
# => nil
Run Code Online (Sandbox Code Playgroud)

  • @phoet make字表示汽车的制造(如丰田,宝马等)http://www.englishforums.com/English/AMakeOfCar/crcjb/post.htm.命名法基于用户的要求 (6认同)

bbo*_*ozo 7

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

[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"
Run Code Online (Sandbox Code Playgroud)

或者,如果你想要委托给类和实例的方法有两个以上,那么可能更干净:

[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"
Run Code Online (Sandbox Code Playgroud)

提醒一句:

不要只是将delegate所有不会改变状态的东西随机地分配到类和实例,因为你将开始遇到奇怪的名称冲突问题.谨慎地做到这一点,只有在你检查后没有别的东西被压扁.


Jas*_*cek 5

你正在以正确的方式做到这一点.类方法(类似于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()
Run Code Online (Sandbox Code Playgroud)

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

#!/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
Run Code Online (Sandbox Code Playgroud)

  • 我不同意 `default_make` 应该是一个实例方法。即使对于这些示例来说更简单,这也不是正确的语义——默认值是类的产物,而不是属于类的对象。 (3认同)
  • 我也不同意。某个东西是否是类方法与“实用程序”无关。它是关于该方法在概念上是否适用于该类或该类的对象。例如,每辆卡车都有不同的序列号,因此 serial_number 是一个实例方法(具有相应的实例变量)。另一方面,车辆类型(返回“卡车”)应该是一个类方法,因为这是所有卡车的属性,而不是特定卡车 (2认同)