(Ошибка аргумента), генерируется при попытке создать экземпляр пользовательского объекта в Ruby - PullRequest
0 голосов
/ 03 февраля 2019

Я хочу создать экземпляр объекта из класса, который я написал в другом файле.Я получил 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)

Что я сделал не так?

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

В 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, которое определяет два метода с именами slots и initialize, перезаписывая метод, который вы только что определили.Обратите внимание, что это напечатает предупреждение:

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

Вы должны всегда читать предупреждения, разработчики Ruby не тратят тяжелую работу, вкладывая их просто для удовольствия!

Решение состоит в том, чтобы убрать запятую, указывающую Ruby искать второй аргумент.

В вашем коде есть вторая ошибка, а именно, что вы ошиблись Array в Lot#initialize.

ИЕсть несколько стилистических улучшений, которые вы можете сделать:

  • Нет необходимости передавать путь и расширение имени файла в require_relative.Это должно быть require_relative 'lot'.
  • Неинициализированные переменные экземпляра оцениваются в nil, поэтому нет необходимости инициализировать @lot в nil.
  • $stdin и $stdout являются значениями аргументов по умолчанию для параметров ключевых слов stdin: и 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
0 голосов
/ 03 февраля 2019

Удалить запятую после

attr_reader :slots,

это будет

attr_reader :slots

И посмотрите, вы пытаетесь создать экземпляр массива (и не должно быть во множественном числе) на лот.rb

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

это будет

  def initialize(size)
    @slots = Array.new(size)
  end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...