Ruby: 从另一个需要属性的方法调用方法

Ruby: Calling a method from another method that needs an attribute

基本上,我有两个方法和一个数组。我正在设置 CLI 界面。我有一种方法 'call' 通过其他方法运行。一种这样的方法需要一个参数。所有这些方法都在同一个 class.

class CLI

  array = ["test"]

  def method_2
    method_1
  end

  def method_1(array)
    puts array
  end

end

我想要上面的输出数组。但是,当我调用 class 的新实例时,我得到了错误的参数数量。我不知道在哪里添加所需的参数。

感谢您的宝贵时间。

-M

我不清楚你想做什么,但听起来你想要的是至少有一个(或多个)方法来打印出 a 的当前值变量,但您不想在调用这些方法时将该变量作为参数传递给它们。

您无法通过定义默认参数(例如 def method_1(array=['test']) 来实现这一点,因为该默认参数仅在定义该方法时计算一次,并且该默认值将永远是该方法时的值首次定义(未更新)。

因此将您的代码更改为如下所示:

class CLI

  @@array = ["test"]

  def method_2
    method_1
  end

  def method_1
    puts @@array
  end

end

@@ 前缀表示一个 class 变量:class 的所有实例将共享该变量的相同值。然后确保 @@array 的值保持最新。您可能想要重新设计您的程序,但除了风格和最佳实践问题,这里有适合您的答案。

通常的做法是在调用时将参数传递给 method_1,但是如果您希望 method_2 调用 method_1 而您不想将其作为参数传递给 method_2,那么您就别无选择(这就是为什么我说您可能想要重新设计界面)。

通常在面向对象的设计中,您将数据和作用于对象中数据的方法封装起来。在 Ruby 中,您使用实例变量创建对象的属性:

class CLI
  def initialize(array = [])
    @array = []
  end

  def method_2
    method_1
  end

  def method_1
    puts @array
  end
end

cli = CLI.new(["Hello", "World"])
cli.method2  

实例变量使用印记@。它们被认为是私有的,因为即使 Ruby 不对实例变量使用 private 关键字,它们也仅限于实例。

Classes也可以有实例变量:

class CLI
  @array = ["Hello", "World"]

  def self.hello
    puts @array.join(" ")
  end

  def you_cant_access_it_from_an_instance
    @array
  end
end

CLI.hello # Hello World
CLI.new.you_cant_access_it_from_an_instance # nil

这是一个“class”实例变量,它属于 class 本身——它不与子classes 共享。这是有效的,因为在 Ruby class 中是对象 - Class class.

的实例

Ruby 也有 class 个变量,它们在 class 及其所有后代之间共享:

class Foo

  @@array = ["Hello", "World"]
    
  def self.hello
    puts @@array.join(" ")
  end

  def self.array=(val)
    @@array = val
  end
end

class Bar < Foo; end
Bar.array = ['Oh', 'noes']
Foo.hello # Oh noes

它们在线程安全方面存在严重问题,由于意外行为,最好避免使用。

我认为您正在做的事情的一个常见模式是工厂方法,该方法使用其输入创建一个新实例,然后调用其调用方法:

class CLI
  def initialize(*args)
    @args = args
  end

  def call
     puts @args.inspect
     # do something awesome
  end

  # factory method thats basically just a convenience
  def self.call(*args)
    new(args).call
  end
end

CLI.call(*ARGV) # passes the command line arguments