何时在Ruby方法中使用`self.foo`而不是`foo`?

39

这不是专门针对Rails的 - 我只是以Rails为例。

我在Rails里有一个模型:

class Item < ActiveRecord::Base

  def hello
    puts "Hello, #{self.name}"
  end
end

假设 Item 模型(类)有一个名为 name 的方法,那么我什么时候需要使用 self.name,什么时候可以直接使用 name (例如,#{name})?


1
这也是让我困惑的一个问题。 - sevenseacat
3个回答

67
  1. 在调用方法时,通常不需要使用self.,习惯上更倾向于省略。

  2. 调用setter方法时必须使用 self.foo = xxx,而不是foo = xxx,以便Ruby意识到您不是要创建一个新的局部变量。

    • 同样,在极少数情况下,如果已经存在一个与方法同名的局部变量do_something,则必须使用self.do_something来调用该方法,因为仅使用do_something将读取该变量。
  3. 不能使用self.foo(...)来调用私有方法,而应该只调用foo(...)


10

如果省略 self,Ruby会先查找具有该名称的局部变量,然后查找实例方法。写self.不是惯用法。无论如何,在赋值时必须写self.something = value

请注意,在调用私有方法时,不能使用self(调用受保护的方法没有问题):

class A
  def foo; self.bar; end

private

  def bar; "bar"; end
end

A.new.foo  
# private method `bar' called for #<A:0x7f49193584f0> (NoMethodError)

0

按照本教程的指导,您无需使用self指针。但我认为this(或在我们的情况下是self)指针用于解决名称冲突。实际上,@nameself.name是相同的语句(如果您的类中没有name方法)。例如:

class Moo
  attr_accessor :name

  def moo(name)
    name = name # O_o which *name* should i use?
  end

  def foo(name)
    @name = name # the same as *self.name = name*
  end

  def hello
    puts self.name # the same as *puts @name*
  end
end

a = Moo.new
a.hello() # should give no output

a.moo('zaooza')
a.hello() # Hey! Why does it prints nothing?

a.foo('zaooza')
a.hello() # whoa! This one shows 'zaooza'!

尝试运行这段代码,你就会看到 =)


4
还有一个特殊情况:命名为foo=的方法必须通过self.foo=调用,否则它会定义一个名为foo的新变量。 - Marcel Jackwerth
是的,你说得对。抱歉,我忽略了这一点,完全忘记了运算符... - shybovycha
5
@nameself.name绝对不是同一条语句。self.name是一个方法调用,而@name是一个实例变量。只不过在你的示例中(但不在原始帖子中),self.name是一个返回@name的方法。在原始帖子的示例中,self.name将获取存储在数据库中的值,而@name将简单地为nil,因此它们绝对不是相同的。 - sepp2k
3
不,这并没有被纠正。如果没有“name”方法,“self.name”将会导致“NoMethodError”。 “self.name”始终是一个方法调用,永远不是变量(尽管它很可能返回变量的内容)。 - sepp2k
Sepp是正确的。此外,就惯用语而言,在Ruby中我从未见过有人在方法调用时使用空括号。 - Matt Briggs

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