【问题标题】:Why is my ruby method always returning true?为什么我的 ruby​​ 方法总是返回 true?
【发布时间】:2012-12-05 21:22:32
【问题描述】:

通过 codeschool 的 ruby​​-bits 课程,我试图了解这些类是如何工作的——我有一个 Game 类和一个名为 Library 的集合类,用于存储游戏集合。

class Game
  attr_accessor :name, :year, :system
  attr_reader :created_at

  def initialize(name, options={})
    self.name = name
    self.year = options[:year]
    self.system = options[:system]
    @created_at = Time.now
  end


  def ==(game)
    name == game.name && 
    system == game.system &&
    year == game.year
  end
end

库类:

class Library
  attr_accessor :games

  def initialize(*games)
    self.games = games
  end

  def has_game?(*games)
    for game in self.games
      return true if game == game
    end
    false
  end
end

现在我创建了一些游戏:

contra = Game.new('Contra', {
  year: 1994,
  system: 'nintendo'
})

mario = Game.new('Mario', {
  year: 1996,
  system: 'SNES'
})

sonic = Game.new('Sonic', {
  year: 1993,
  system: 'SEGA'
})

并实例化一个新的集合:

myCollection = Library.new(mario, sonic)

当我尝试使用has_game? 方法查找某个游戏是否在myCollection 中时,我总是得到true

puts myCollection.has_game?(contra) #=> returns **true** 尽管它从未作为集合的一部分插入。

我做错了什么?

【问题讨论】:

  • 因为game == game 始终为真。
  • 那么问题出在 Game 类中的 ==(games) 实例方法吗?我该如何解决?我需要检查游戏是否是收藏的一部分
  • 不,问题是您将game 与自身进行比较。

标签: ruby class collections boolean


【解决方案1】:

这里有几件事是错误的:

  1. 而不是使用self.XXXX 创建实例变量,你应该 使用@XXXX,它直接访问值,使用self实际执行 另一个方法调用,请参阅此处了解更多详细信息:Instance variable: self vs @

  2. 正如其他人提到的game == game 将始终返回true,答案是 已发布 不允许将多个游戏传递给 has_game?

以下是我的正确工作的更改:

class Game
  attr_accessor :name, :year, :system
  attr_reader :created_at

  def initialize(name, options={})
    @name       = name
    @year       = options[:year]
    @system     = options[:system]
    @created_at = Time.now
  end


  def ==(game)
    @name == game.name && 
    @system == game.system &&
    @year == game.year
  end
end

class Library
  attr_accessor :games

  def initialize(*games)
    @games = games
  end

  # only returns true if this Library
  # has ALL of the games passed to has_game? 
  def has_game?(*_games)
    _games.each do |game|
      return false if not @games.include?(game)
    end

    return true
  end
end

contra = Game.new('Contra', {
  year: 1994,
  system: 'nintendo'
})

mario = Game.new('Mario', {
  year: 1996,
  system: 'SNES'
})

sonic = Game.new('Sonic', {
  year: 1993,
  system: 'SEGA'
})

myCollection = Library.new(mario, sonic)
puts "Collection has Contra? #{myCollection.has_game?(contra)}"
puts "Collection has Sonic and Mario #{myCollection.has_game?(sonic, mario)}"

输出:

Collection has Contra? false
Collection has Sonic and Mario true

【讨论】:

  • 太棒了!这正是我想要的
  • 你的 "has_game?()" 方法只返回最后一个游戏是否包含在 @games 中......使用数组相交可能会更容易,或者你可以这样迭代:def has_game?( *_games);_games.map{|game|@games.include?(game)}.all?;end
  • @Pavling你说得对,我忘了在假的情况下爆发。
  • @Pavling 我最终以更好的方式重写了该方法,谢谢!
【解决方案2】:
return true if game == game

我认为这种说法可能会导致问题。

总是如此。

你可能想要这样的东西:

def has_game?(wanted)
  for game in self.games
    return true if game == wanted
  end
  false
end

【讨论】:

    猜你喜欢
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2012-04-03
    • 2021-09-11
    相关资源
    最近更新 更多