首页 > 解决方案 > 尝试在 Ruby 中实例化自定义对象时抛出(参数错误)

问题描述

我想从我写在不同文件上的类中实例化一个对象。我得到的是wrong number of arguments (given 1, expected 0) (ArgumentError)

这是主要代码

# ./lib/parking_lot
require_relative './lot.rb'

class ParkingLotInterface

  def initialize(input: $stdin, output: $stdout)
    @input, @output = input, output
    @lot = nil
  end

  def prompt_input
    @lot = Lot.new(10)   
  end
end

parking_lot_interface = ParkingLotInterface.new(input: $stdin, output: $stdout)

parking_lot_interface.prompt_input

这是对象类

# ./lib/lot
class Lot
  attr_reader :slots, 

  def initialize(size)
    @slots = Arrays.new(size)
  end
end

在我尝试实例化一个新的 Lot 对象的那一行引发了错误。查看互联网,有同样问题的人被告知他们没有def initialize在课堂上指定,或者他们输入错误。然而,我做了他们都说的,我仍然面临wrong number of arguments (given 1, expected 0) (ArgumentError)

我做错了什么?

标签: rubyoop

解决方案


在 Ruby 中,方法定义也是表达式(实际上,在 Ruby 中,一切都是表达式,没有语句),因此它们的计算结果是一个对象。方法定义表达式求值为 aSymbol表示已定义方法的名称。

所以,

def initialize(*) end
#=> :initialize

在您的代码中,后面有一个逗号attr_reader :slots,这意味着您将两个参数传递给attr_reader,即符号:slots和表达式def initialize(…) … end。由于 Ruby 是一门严格的语言,因此在执行自身attr_reader之前,将首先评估to 的参数。attr_reader

所以,首先发生的是方法定义表达式被求值。这定义了一个名为的(私有)方法initialize。它还计算符号:initialize

接下来,对表达式attr_reader :slots, :initialize进行求值,它定义了两个名为slotsandinitialize的方法,从而覆盖了您刚刚定义的方法。请注意,这将打印一个警告:

lot.rb:3: warning: method redefined; discarding old initialize
lot.rb:5: warning: previous definition of initialize was here

您应该始终阅读警告,Ruby 开发人员不会为了好玩而花费大量精力投入其中!

解决方案是删除告诉 Ruby 寻找第二个参数的逗号。

您的代码中有第二个错误,即您ArrayLot#initialize.

而且,您可以进行一些风格上的改进:

  • 无需将路径和文件扩展名传递给require_relative. 应该是require_relative 'lot'
  • 未初始化的实例变量评估为nil,因此无需初始化@lotnil
  • $stdin$stdoutstdin:stdout:关键字参数的默认参数值,因此无需显式传递它们。
  • 很少需要创建特定大小的数组,因为 Ruby 数组是动态的并且可以随时更改其大小。

考虑到所有这些,您的代码将如下所示:

# ./lib/parking_lot
require_relative 'lot'

class ParkingLotInterface
  def initialize(input: $stdin, output: $stdout)
    @input, @output = input, output
  end

  def prompt_input
    @lot = Lot.new(10)   
  end
end

parking_lot_interface = ParkingLotInterface.new

parking_lot_interface.prompt_input

# ./lib/lot
class Lot
  attr_reader :slots

  def initialize(size)
    @slots = Array.new(size)
    # could be @slots = []
    # depending on how you use `@slots` later
  end
end

推荐阅读