使用ruby self关键字?

Ank*_*oni 62 ruby self instance

根据我对self关键字的理解,它只是引用了类的当前实例.这不是一直都是默认行为吗?例如,不是

self.var_one = method(args)相当于var_one = method(args)

如果是这样那么自我的用途是什么?

And*_*rew 117

有几个重要的用途,其中大部分基本上是为了消除实例方法,类方法和变量之间的歧义.

首先,这是定义类方法的最佳方法.IE:

class Foo
  def self.bar
    "class method bar"
  end

  def bar
    "instance method bar"
  end
end

Foo.bar  #returns "class method bar"

foo = Foo.new
foo.bar #returns "instance method bar"
Run Code Online (Sandbox Code Playgroud)

此外,在实例中,self指向实例,在类方法中它引用类,并且它总是可以用于区分局部变量.

class Bar
  def self.foo
    "foo!"
  end

  def baz
    "baz!"
  end

  def self.success
    foo #looks for variable foo, doesn't find one, looks for class method foo, finds it, returns "foo!"
  end

  def self.fail
    baz #looks for variable baz, doesn't find one, looks for class method baz, doesn't find one, raises exception
  end

  def instance_success
    baz #looks for variable baz, doesn't find one, looks for instance method baz, finds it, returns "baz!"
  end

  def instance_fail
    foo #looks for variable foo, doesn't find one, looks for instance method foo, doesn't find one, raises exception
  end

  def local_variable
    baz = "is my favorite method"
    baz #looks for variable baz, finds it, returns "is my favorite method"
  end

  def disambiguate
    baz = " is my favorite method"
    self.baz + baz #looks for instance method baz, finds it, looks for local variable baz, finds it, returns "baz! is my favorite method"
  end
end
Run Code Online (Sandbox Code Playgroud)

因此,最后,您可以避免self在许多情况下使用,但是继续使用它以确保您以后不会无意中创建命名冲突通常会有所帮助.有时那些可能会产生很难找到的错误.最后,这通常是个人风格的问题.


更新:如评论中所述,还有一个非常重要的事情:

在课堂上,如果您有这样的方法:

def bar=(string)
  ...
end
Run Code Online (Sandbox Code Playgroud)

在另一种方法中,你打电话:

def other_method
  bar = "abcd"
end
Run Code Online (Sandbox Code Playgroud)

它不会调用你的bar =方法,它会创建一个局部变量条.因此,在这种情况下,您使用self告诉ruby不要创建局部变量,如下所示:

def other_method
  self.bar = "abcd"
end
Run Code Online (Sandbox Code Playgroud)

如果你想用一个方法的名称来取一个参数,同样的事情适用:

def example
  ...
end

def other_thing(example)
  self.example(example)
end
Run Code Online (Sandbox Code Playgroud)

如果你离开了自己,它会认为你的意思是同名的局部变量.

因此,通常,self in in method name用于区分类和实例变量,以及当Ruby需要帮助区分方法调用和局部变量或局部变量赋值时使用它的任何其他位置.

我希望这是有道理的!

  • 这是一个更彻底的答案,除了它不包括任务警告.关于用法的博客文章也很好:http://www.jimmycuadra.com/posts/self-in-ruby,具体包括作业.如果不使用self,则无法调用赋值方法(如第一个答案中所述). (3认同)
  • 对Java人员非常有帮助=) (2认同)
  • 可能,最好勾勒出"你只能在类方法中访问类变量/方法"的原则 (2认同)

sep*_*p2k 55

在大多数情况下self.foo确实是多余的,因为你可以只foo为相同的效果写,但在这种情况下它不是,而且self是必需的.

var_one = method(args)将创建一个名为的局部变量var_one,它不会调用任何方法或执行任何其他操作self.

self.var_one = method(args)会调用该方法var_one=self的说法method(args).

使用self非可选的另一种情况是,如果您想将其作为参数传递给方法,即some_method(self)- 如果没有self关键字,则无法执行此操作.

  • @Ankit Soni:如果你向'self`发送任何消息(例如,`self.foo`),它就会调用你班级的`foo`方法.`var_one =`只是一个setter方法.如果你想`var_one`是一个变量,你不能使用`self`(它只对调用方法有用).如果您正在寻找实例变量,那么您只需在标识符前加上"@"(例如,`@ var_one`) (5认同)
  • @Ankit:你的setter方法将按你所定义的方式执行.但是它几乎肯定不会创建一个名为`var`的局部变量,因为该变量是本地的,只会存在于setter方法中,因此没有任何效果.如果使用`attr_accessor`定义了setter方法,那么它将创建一个名为`@ var`的*实例变量*.因此,在特定情况下,`@ var ="foo"和`self.var ="foo"`会做同样的事情.但是`var ="foo"`不会. (4认同)