为什么工作不正常时会出现这种情况?

Why is this case when not working properly?

  if ( item::class == RPG::Weapon )
    print "yup"
  end
  case item::class
  when RPG::Item
    type = 0
  when RPG::Weapon
    type = 1
  when RPG::Armor
    type = 2
  else
    type = 10
  end

我是 Ruby 的新手。 if 语句运行良好并打印 "yup",但 case 语句无法正常工作并将 type 设置为 10。我是对某事视而不见还是什么?

只需 case item 就足够了 - 不需要 case item::class

Ruby 中的大小写匹配是通过不需要此类特定子句的模糊匹配 (===) 算法完成的。

Module#=== tests if the argument is an instance of self. item.class can never be an instance of anything but Class,特别是,它永远不会是 RPG::WeaponRPG::Armor 的实例,因此 when 分支的 none 将永远匹配,您将始终获得 else 分支。

顺便说一句:使用名称空间解析运算符 :: 代替消息发送运算符 . 进行消息发送 非常 不合常理且令人困惑(并且不适用于名称以大写字符开头的方法)。事实上,我认为 matz 认为将此功能添加到 Ruby 是一个错误。

还要注意case是一个表达式,其实所有在Ruby中都是一个表达式

我会这样写代码:

type = case item
  when RPG::Item
    0
  when RPG::Weapon
    1
  when RPG::Armor
    2
  else
    10
end

但是,一般来说,条件语句是一种代码味道。 Ruby是一种面向对象的语言,多态性(即基于self类型的方法调度)是all the conditional you need! In fact, in this very example, you are manually examining the class of item in order to determine its type, but that is exactly what method dispatch does anyway! Personally, I would refactor这样的代码:

class RPG::Item
  def type
    0
  end
end

class RPG::Weapon
  def type
    1
  end
end

class RPG::Armor
  def type
    2
  end
end

class RPG::Object # or whatever your baseclass is
  def type
    10
  end
end

现在,当您添加一种新的游戏对象时,您不必通过向 case 表达式添加新分支来修改现有代码。您只需添加新的 class,无需修改任何现有代码。