Rubyクラスの型とcaseステートメント


135

違いは何ですか

case item.class
when MyClass
  # do something here
when Array
  # do something different here
when String
  # do a third thing
end

そして

case item.class
when MyClass.class
  # do something here
when Array.class
  # do something different here
when String.class
  # do a third thing
end

何らかの理由で、これらの最初の1つは時々機能し、2つ目は機能しません。また、2つ目は機能し、最初の1つは機能しません。どうして?それを行う「適切な」方法はどれですか?


1
文字列はクラスです。クラスのクラスはClassです。
Volte

はのインスタンスかどうかを確認MyClass === objするためにModule#===メソッドを使用することに注意してください。objMyClass
セルジオ

回答:


234

以下を使用する必要があります。

case item
when MyClass
...

私は同じ問題を抱えていました: 「場合」でErrno :: ECONNRESETクラスをキャッチする方法?


1
ありがとう!申し訳ありませんが、いくつかの検索ではその前の質問が見つかりませんでした。caseステートメントで===を使用することはよくある問題のようですが、これが問題であることがわかりました。これはおそらくチュートリアルなどでもっと頻繁に指摘されるべきです(しかし、多くのチュートリアルの作成者はこれも認識していません)。
デイジーソフィアホールマン

4
ActiveRecordを使用する場合は言及されていない警告。クラス比較のActiveRecord ===メソッドは.is_a?を使用します。これは、クラスのサブクラスがcaseステートメントでtrueに評価されることを意味します。github.com/rails/rails/blob/…–
Jeremy Baker、

60

ええ、ナキロンは正しいですwhen。節で指定されたオブジェクトに対してthreequal ===演算子がどのように機能するかを知っている必要があります。Rubyで

case item
when MyClass
...
when Array
...
when String
...

本当に

if MyClass === item
...
elsif Array === item
...
elsif String === item
...

caseがthreequalメソッド(MyClass.===(item)たとえば)を呼び出していることを理解し、そのメソッドを定義して必要な処理を実行し、caseステートメントをprecisionwで使用できます。


私がarr = []気づいたらif Array === arr、trueと評価されますがif arr === Arrayfalseと評価されます。誰かが説明してくれませんか?
ダニエル

4
===は、クラスの設計者が実行したいことを何でも実行できるように定義できる単なるメソッドです。また、a === bは実際にはa。=== bを意味するので、aとbを入れ替えると、異なる動作が得られることにも注意してください。===が可換であるという保証はありません。実際、Array === Arrayはfalseですが、Object === Objectはtrueなので、Arrayは===のセマンティクスを再定義しています。
Fred


5

Rubyでは、クラス名はClass特定のクラスを説明する型のオブジェクトを参照する定数です。つまりMyClass、Rubyで言うことMyClass.classはJavaで言うことと同じです。

obj.classClassのクラスを説明するタイプのオブジェクトですobjobj.classisの場合MyClass、(大まかに)objを使用して作成されましたMyClass.new。を使用して作成されたオブジェクトを説明するMyClassタイプのClassオブジェクトですMyClass.new

MyClass.classMyClassオブジェクトのクラスです(これは、を使用して作成されたオブジェクトを記述するタイプのオブジェクトのクラスです)。つまり、です。ClassMyClass.newMyClass.class == Class


1

item変数の性質によって異なります。それがオブジェクトのインスタンスである場合、例えば

t = 5

その後

t.class == Fixnum

しかし、それ自体がクラスの場合、たとえば

t = Array

それからClassオブジェクトになるので、

t.class == Class

編集「ケースタイム」でErrno :: ECONNRESETクラスをキャッチする方法を参照してください私の答えは間違っている可能性があるため、ナキロンが述べたように。


Rubyでは、すべてが「オブジェクトのインスタンス」です。
Eric Duminil 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.