【问题标题】:Ruby - Method call to object in arrayRuby - 对数组中对象的方法调用
【发布时间】:2009-07-13 20:20:07
【问题描述】:

我正在为学校开展一个 Ruby 项目,遗憾的是无法在我的文献中找到这个问题的答案。

我有一系列露营地,每个露营地都有一位客人。我像这样初始化很多:

lots = Array.new

for i in (1..36)
  lots[i] = Lot.new(i)
end

再往下,我创建了一个Guest 对象,对其进行初始化,现在我想将Guest 添加到我的Lot 中。 Lot 类中的方法如下所示:

def AddGuest(guest)
  @guest = guest
end

当我想调用该方法时,问题就来了,因为LotArray 中。

lots[lotnumber].AddGuest(guest)

这个调用给了我错误:

undefined method `+@' for #<Guest:0x2c1ff14> (NoMethodError)

我使用过require,所以这些类相互了解。我很难理解 Ruby,我的错误可能是我尝试访问 Array 类中的 AddGuest 方法吗?我习惯用 C++ 做这样的事情。

以下是完整的源代码(至少是相关部分)。

整个Lot类:

class Lot

  def initialize(number)
    @gauge = rand(2000) + 2000
    @number = number
    @guest = false
  end

  def Occupied()
    return @guest
  end

  def AddGuest(guest)
    @guest = guest
  end

  def RemoveGuest()
    @guest = false
  end

end

main.rb 的部分内容

#includes
require 'guest'
require 'lot'

#initiate comparison variables
userInput = "0"
numberOfGuests = 0
foundLot = false
guests = Array.new
lots = Array.new

#initialize lot list
for i in (1..36)
  lots[i] = Lot.new(i)
end

玩家输入省略

#make sure lot is not taken
while foundLot == false do
  lotnumber = rand(35)+1
  if lots[lotnumber].Occupied() == false then
    foundLot = "true"
  end
end
foundLot = false

guest = Guest.new(firstName, lastName, adress, phone, arrival, lotnumber)
guests.insert(numberOfGuests, guest)
numberOfGuests++

lots[lotnumber].AddGuest(guest) #this is where error hits

end

end

end

【问题讨论】:

  • 你能发布完整的源代码吗? AddGuest 方法是否定义在类的范围内?
  • 您是否可能不小心将 AddGuest 置于私有或受保护状态?
  • 仅供参考,您可以更简洁地创建地段为lots = (1..36).collect {|n| Lot.new n}。 Ruby 消除了很多显式循环。

标签: ruby arrays


【解决方案1】:

该错误似乎与您使用 ++ 运算符有关,这很自然地在 C++ 中受支持,但在 Ruby 中不受支持。

等价于:

numberOfGuests += 1

【讨论】:

  • 解决了!感谢大家的快速回答。现在,如果我可以停止在行尾添加分号... :)
【解决方案2】:

一些小技巧...

[1]

写这个稍微更惯用的方式...

for i in (1..36)
  lots[i] = Lot.new(i)
end

会...

(1..36).each { |i| lots[i] << Lot.new(i) }

[2]

要从批次中删除客人,您可能希望将其设置为 nil 而不是 false。这是我的建议……

class Lot

  def initialize(number)
    @gauge = rand(2000) + 2000
    @number = number
    # Don't need to set @guest -- it's nil by default.
  end

  # In Ruby, methods that return a boolean often have a "?".
  # Makes it "read better" when you call the method. (See
  # usage sample.)
  def occupied?
    ! @guest.nil?
  end

  # There's a more commonplace way to do this. See below...
  def add_guest(guest)
    @guest = guest
  end

  def remove_guest()
    @guest = nil
  end

end

使用示例:

>> lot = Lot.new(2)
=> #<Lot:0x1300920 @number=2, @gauge=3444>
>> lot.occupied
=> false
>> lot.add_guest('A guest')
=> "A guest"
>> lot.occupied?
=> true
>> lot.remove_guest
=> nil
>> lot.occupied?
=> false

两个...

在类定义中使用attr_accessor 方法是惯例。它们会自动将 getter 和 setter 方法添加到您的类中。如果你想遵循常见的 Ruby 模式,你可以这样做而不是 add_guestremove_guest...

class Lot

  attr_accessor :number, :gauge, :guest

  def initialize(number)
    @gauge = rand(2000) + 2000
    @number = number
  end

  def occupied?
    ! @guest.nil?
  end

end

用法...

irb(main):017:0> lot = Lot.new(3)
=> #<Lot:0xb7f7fca8 @gauge=3186, @number=3>

设置很多客人(如add_guest)...

irb(main):019:0> lot.guest = 'A guest'
=> "A guest"
irb(main):020:0> lot.occupied?
=> true

得到很多客人......

irb(main):025:0> lot.guest
=> "A guest"

删除访客...

irb(main):021:0> lot.guest = nil
=> nil
irb(main):023:0> lot.occupied?
=> false

【讨论】:

  • 其实更好的是使用Array#collect为你做脏活。 (1..36).collect { |i| Lot.new(i) } 虽然这将是 0 索引,而不是示例中的 1 索引。
  • Array.new(36) { |i| Lot.new(i) }
  • 你不想在“lots[i]
  • "# 不需要设置 @guest -- 默认为 nil。" - 如果您使用警告,则使用未初始化的@guest 将生成警告。您的里程可能会有所不同。
【解决方案3】:

通常 Ruby 方法名称不大写。约定很简单:ClassName、CONSTANT、method_name。

由于您有一个 Lot 对象数组,因此以下应该是正确的:

lots.class # => Array
lots[1].class # => Lot

调用的方法应该是为Lot定义的。

【讨论】:

  • 对不起,如果我不清楚,调用的方法是为 Lot 定义的。当我谈论 Array 类时,我指的是内置类,我还没有自己编写。
  • 我刚刚发布了针对您粘贴的代码示例的不同回复。我希望这会有所帮助。
猜你喜欢
  • 2012-05-20
  • 2017-10-24
  • 1970-01-01
  • 2017-11-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 2018-10-21
  • 1970-01-01
相关资源
最近更新 更多