什么时候在Ruby中使用'self'

Tom*_*man 9 ruby

这个方法:

  def format_stations_and_date
    from_station.titelize! if from_station.respond_to?(:titleize!)
    to_station.titleize! if to_station.respond_to?(:titleize!)
    if date.respond_to?(:to_date)
      date = date.to_date
    end
  end
Run Code Online (Sandbox Code Playgroud)

如果date为nil ,则会出现此错误:

NoMethodError (You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_date):
  app/models/schedule.rb:87:in `format_stations_and_date'
  app/controllers/schedules_controller.rb:15:in `show'
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改date = date.to_dateself.date = self.date.to_date,该方法可以正常工作.

这是怎么回事?一般来说,我self什么时候写?

编辑:这与问题无关,但请注意,没有"标题!" 方法.

sep*_*p2k 43

每当你想在self上调用setter方法时,你必须编写self.foo = bar.如果您只是编写foo = bar,那么ruby解析器会将其识别为变量赋值,并且从现在开始将foo视为局部变量.为了让解析器实现,你想要调用一个setter方法,而不是分配一个局部变量,你必须写obj.foo = bar,所以如果对象是self,self.foo = bar


Jul*_*lik 7

您可以使用self消除实例方法名称和局部变量之间的歧义(允许在同一范围内具有相同的名称).换句话说,只有在作用域中没有同名的本地或块变量时,才会有方法名称解析.看吧:

class Foo
  attr_accessor :boo
  def do_boo
    boo = 123
    puts "Locvar: #{boo} Method: #{self.boo}"
  end
end
Foo.new.do_boo
Run Code Online (Sandbox Code Playgroud)

原因如下:假设您有一个实现方法的模块.这个方法为它的内部局部变量"foo"赋予了一些东西,用于某些计算.如果跳过"self"部分,该方法将对其类包含模块的对象进行"foo ="方法调用,这不是作者的意图,可能是彻头彻尾的灾难性的.

class Foo
  def bar=(new_value_of_bar)
    set_off_nukes(new_value_of_bar / 3)
  end
end

module InnocentModule # written by a different author elsewhere
  def do_useful_stuff
    ...
    bar = Math.sin(something) # we're dead
  end
end
Foo.send(:include, InnocentModule)
Run Code Online (Sandbox Code Playgroud)

你必须使用self的另一个关键部分是在调用Object#类方法时,因为简单地说"class"意味着Ruby的类关键字.