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

时间:2009-08-09 19:31:10

标签: 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

date为零时失败,显示此错误:

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'

但是,如果我将date = date.to_date更改为self.date = self.date.to_date,则该方法可以正常运行。

发生了什么事?一般来说,我何时必须写self

修改:这与问题无关,但请注意,没有“标题化”!方法

2 个答案:

答案 0 :(得分:42)

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

答案 1 :(得分:7)

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

class Foo
  attr_accessor :boo
  def do_boo
    boo = 123
    puts "Locvar: #{boo} Method: #{self.boo}"
  end
end
Foo.new.do_boo

原因如下:假设你有一个实现方法的模块。这个方法为它的内部局部变量赋予了一些东西 “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)

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