Why is this case when not working properly?

后端 未结 2 1576
隐瞒了意图╮
隐瞒了意图╮ 2021-01-23 08:31
  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条回答
  • 2021-01-23 09:11

    Just case item will be sufficient - no need for case item::class.

    Case matching in Ruby is done with a fuzzy matching (===) algorithm that doesn't need such specific clauses.

    0 讨论(0)
  • 2021-01-23 09:15

    Module#=== tests if the argument is an instance of self. item.class can never be an instance of anything but Class, in particular, it will never be an instance of either RPG::Weapon or RPG::Armor, therefore none of the when branches will ever match and you will always get the else branch.

    By the way: using the namespace resolution operator :: for message sends instead of the message sending operator . is extremely un-idiomatic and confusing (and won't work for methods whose name starts with an uppercase character). In fact, I believe matz considers adding this feature to Ruby a mistake.

    Note also that case is an expression, in fact, everything in Ruby is an expression.

    I would write the code as follows:

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

    However, in general, conditionals are a code smell. Ruby is an object-oriented language, polymorphism (i.e. method dispatching based on the type of self) is 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 this code like this:

    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
    

    Now when you add a new kind of game object, you don't have to modify your existing code by adding a new branch to your case expression. You just add the new class, without needing to modify any existing code.

    0 讨论(0)
提交回复
热议问题