10

Ruby1.9.2とRubyonRails3.2.2を使用しています。私は次の方法を持っています:

# Note: The 'class_name' parameter is a constant; that is, it is a model class name.
def my_method(class_name)
  case class_name
  when Article then make_a_thing
  when Comment then make_another_thing
  when ...     then ...     
  else raise("Wrong #{class_name}!")
  end  
end

上記のステートメントで、などのメソッド呼び出しを実行するとcase、常にelse「部分」が実行される理由を理解したいと思います。my_method(Article)my_method(Comment)

どうすれば問題を解決できますか?誰かがこれを処理する方法についてアドバイスがありますか?

4

3 に答える 3

4

バックグラウンドで === 演算子を使用するため、オブジェクト参照をメソッドに渡すため、これらは失敗します。例えば

obj = 'hello'
case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

一方、これはうまく機能します:

obj = 'hello'
case obj  # was case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

「Ruby で switch ステートメントを記述する方法」への関連する回答を参照してください https://stackoverflow.com/a/5694333/1092644

于 2012-10-23T00:46:00.737 に答える
4

これは、casecall===および===on Class (または具体的には Class の派生元である Module) が次のように実装されているためです。

mod === objtrueまたはfalse

大文字と小文字が等しい -が のインスタンスまたはの子孫のいずれtrueかである場合に返されます。モジュールには限定的に使用されますが、オブジェクトをクラス別に分類するために case ステートメントで使用できます。objmodmod

Classこれは、 &以外の定数Module(例: Foo) に対しては、Foo === Foo常に を返すことを意味しますfalse。その結果、ステートメントで常にelse条件を取得します。case

case代わりに、クラスの代わりにオブジェクト自体を呼び出すか、if文を使用してください。

于 2012-10-23T00:51:24.810 に答える
1

to_s名前の等価性を比較したいだけの場合は、クラス定数に追加できます。

def my_method(class_name)
  case class_name.to_s
  when 'Article'
    make_a_thing
  when 'Comment'
    make_another_thing

  ... ...

  end  
end
于 2015-12-23T17:30:12.183 に答える