【问题标题】:(Argument Error) thrown when trying to instantiate a custom object in Ruby尝试在 Ruby 中实例化自定义对象时抛出(参数错误)
【发布时间】:2019-02-03 05:58:25
【问题描述】:

我想从我写在不同文件上的类中实例化一个对象。我得到的是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)

我做错了什么?

【问题讨论】:

    标签: ruby oop


    【解决方案1】:

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

    所以,

    def initialize(*) end
    #=> :initialize
    

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

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

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

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

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

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

    您的代码中还有第二个错误,即您在Lot#initialize 中拼错了Array

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

    • 无需将路径和文件扩展名传递给require_relative。应该是require_relative 'lot'
    • 未初始化的实例变量评估为nil,因此无需将@lot 初始化为nil
    • $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
    

    【讨论】:

      【解决方案2】:

      删除后的逗号

      attr_reader :slots,
      

      应该是

      attr_reader :slots
      

      看看,你正在尝试在 lot.rb 上实例化数组(并且不能是复数形式)

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

      应该是

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-21
        • 2012-04-11
        • 2016-12-26
        • 1970-01-01
        相关资源
        最近更新 更多