【问题标题】:When to use 'self' in Ruby何时在 Ruby 中使用“self”
【发布时间】:2009-08-09 19:31:10
【问题描述】:

这个方法:

  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 为 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'

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

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

编辑:与问题无关,但请注意没有“titleize!”方法。

【问题讨论】:

标签: ruby


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以使用 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 方法时,因为简单地说“class”意味着 Ruby 的类关键字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 2015-03-03
      • 2015-11-12
      • 1970-01-01
      相关资源
      最近更新 更多