【问题标题】:How to pass all local variables when calling a method调用方法时如何传递所有局部变量
【发布时间】:2016-02-15 10:36:00
【问题描述】:

我想知道是否有一种简单的方法可以在调用方法时传递所有局部变量,而不是一个一个地作为参数传递。我想要以下内容:

class Greeting
  def hello
    message = 'HELLO THERE!'
    language = 'English'
    say_greeting
  end

  def konnichiwa
    message = 'KONNICHIWA!'
    language = 'Japanese'
    say_greeting
  end

  private def say_greeting
    puts message
  end
end

Greeting.new.hello

显示HELLO THERE!。但它返回一个错误:NameError: undefined local variable or method 'message'

我尝试local_variables 将所有局部变量作为符号数组获取。但我似乎无法访问实际变量,因为似乎没有像 local_variable_get 这样的 Ruby 方法。

问题背景

在我的 Rails 应用程序中,我有一个控制器,它具有三种用于不同视图文件的更新方法。它们的行为完全相同(它们都将更新资源、显示错误(如果有)等)。他们唯一的主要区别是

  1. 不成功时要渲染的模板
  2. 成功时重定向网址
  3. 刷写成功消息

我只有三个变量,所以将它们作为参数传递确实很容易,但我只是想知道是否有一个优雅的解决方案。

【问题讨论】:

  • message 应该与attr_accessor :message 一起使用,或者通过像@message 这样的前缀来使用实例变量。私有方法可以访问与公共方法相同的变量。 privatepublic 只设置其他类可以使用的权限。
  • 我不希望该变量可在类外访问。放置 attr_accessor :message 将允许我做我不想要的Greeting.new.message
  • 然后通过在消息前加上@来使用实例变量。或者您也可以将 attr_accessor 设为私有,然后只能从实例内部访问它
  • 不,没有办法。好吧,binding 对象可能有一些的方法,因为 ruby​​ 就是这样——但它会过于复杂,即使它很简单也不是一个好主意。

标签: ruby local-variables


【解决方案1】:

局部变量的作用恰恰不是您想要做的:将引用封装在方法定义中。并且实例变量可以精确地完成您想要做的事情:在单个对象的不同方法调用之间共享信息。您对局部变量的使用与此相反。

使用实例变量,而不是局部变量。

如果你坚持要在方法之间引用局部变量,那么这里有一个办法:

class Greeting
  def hello
    message = 'HELLO THERE!'
    language = 'English'
    say_greeting(binding)
  end

  def konnichiwa
    message = 'KONNICHIWA!'
    language = 'Japanese'
    say_greeting(binding)
  end

  private def say_greeting b
    puts b.local_variable_get(:message)
  end
end

你不能不传递任何参数,但你可以只传递一个绑定参数,并从那里引用所有局部变量。

【讨论】:

  • 我希望我不能使用实例变量,因为它会将它们添加到内存中,而不是在方法结束时被垃圾收集。我也不希望将这些变量共享给其他方法。但是,如果这似乎是唯一的出路,我会接受你的回答:)
  • 否则,您应该将它们作为参数传递。避免这种情况也违背了语言设计。
  • 哦,我不知道这个绑定! :D 谢谢!
【解决方案2】:

将消息和语言作为实例变量。 然后你可以在私有方法中访问它们。

class Greeting
  def hello
    @message = 'HELLO THERE!'
    @language = 'English'
    say_greeting
  end

  def konnichiwa
    @message = 'KONNICHIWA!'
    @language = 'Japanese'
    say_greeting
  end

  private 

  def say_greeting
    puts @message
  end
end

puts Greeting.new.hello

【讨论】:

  • 如果可能的话,我想只使用局部变量。假设有一个共享 1000 个变量的类。这将为对象增加大量内存。
  • 做一些元编程来构建一个调用该方法的命令行或生成一个临时的公共类,你以后会扔掉。
【解决方案3】:

使用实例变量。在您的方法say_greeting 中,确保您首先调用方法hello,否则@message 的值将是nil

def hello
 @message = "Hello there"
end

def say_greeting
  hello #method call
  puts message
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2012-12-07
    相关资源
    最近更新 更多