在 Ruby 中,类方法内的 self 是指类本身还是一个实例?

18

我知道self是实例方法内部的实例。那么,在类方法中self是否表示类本身?例如,以下代码在Rails中是否可行?

我知道self是实例方法内部的实例。那么,在类方法中self是否表示类本身?例如,以下代码在Rails中是否可行?

class Post < ActiveRecord::Base
  def self.cool_post
    self.find_by_name("cool")
  end
end

5
补充一下之前的答案,因为 Ruby 会默认将接收者作为 self 进行评估,所以你可以直接调用 find_by_name 而不需要加上 self :) - brad
谢谢,有没有情况下指定 self 是个好主意?self.find_by_name 是 Ruby 查找 find_by_name 的第一个地方吗?它会在其他地方查找吗?如果是全局定义的方法(在类外文件中定义的方法),那又怎么样呢? - ma11hew28
我进行了测试。看起来优先顺序是类方法,如果没有找到类方法,则为全局定义的方法。 - ma11hew28
我创建了一张图表,展示了Ruby中方法查找顺序。你可能会发现它很有用。 - Phrogz
至少在 Ruby 1.9.2 中,“全局定义”的方法实际上是 Object 上的私有方法。例如尝试:def foo; end; Object.private_methods.include?(:foo) # => true。这意味着它们基本上位于继承链的顶部,并且是最后被找到的。 - Stéphan Kochen
4个回答

23

没错。在类方法中,self指的是该类本身。(同样也适用于类定义内部,例如在def self.coolpost中的self)

你可以使用irb轻松测试这些小贴士:

class Foo
  def self.bar
    puts self.inspect
  end
end

Foo.bar  # => Foo

5
class Test
    def self.who_is_self
        p self
    end
end

Test.who_is_self

输出:

测试

现在,如果您想要一个与Rails相关的解决方案,它被称为named_scopes:

class Post < ActiveRecord::Base
   named_scope :cool, :conditions => { :name => 'cool' }
end

使用方式如下:

Post.cool

5
许多回答已经提到,但这里是为什么self是类的原因:
点号将self更改为点号之前的任何内容。因此,当您执行foo.bar时,对于bar方法,self是foo。使用类方法没有任何区别。调用Post.cool_post时,将self更改为Post。
这里需要注意的重要事情是,不是定义方法决定self,而是调用方法。这就是为什么这个例子可以正常工作的原因:
class Foo
  def self.bar
    self
  end
end

class Baz < Foo
end

Baz.bar # => Baz

或者这样:
module Foo
  def bar
    self
  end
end

class Baz
  extend Foo
end

Baz.bar # => Baz

4

简短回答:是的

对于这些问题,我喜欢启动irb或./script/console会话

然后你可以执行以下操作来查看魔法:

ruby-1.8.7-p174 > class TestTest
ruby-1.8.7-p174 ?>  def self.who_am_i
ruby-1.8.7-p174 ?>    return self
ruby-1.8.7-p174 ?>    end
ruby-1.8.7-p174 ?>  end
 => nil 
ruby-1.8.7-p174 > TestTest.who_am_i
 => TestTest

愉快地钓鱼吧!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接