web-dev-qa-db-ja.com

Ruby狂気:クラスvsオブジェクト?

私はJRubyで遊んだところです。これは私の最初のRuby=投稿です。Rubyのクラスとオブジェクトを理解するのに苦労しました。他のオブジェクト指向言語のクラスとオブジェクトのように意味するわけではありません。例としては

Class.is_a? Object

trueを返し、

Object.is_a? Object

too

したがって、クラスとオブジェクトは両方ともオブジェクトです

ここに別のものがあります

Class.is_a? Class

trueを返し、

Object.is_a? Class

too

待って、まだ終わってない

 Object.instance_of? Class
 Class.instance_of? Class

どちらも正しい

 Object.instance_of? Object
 Class.instance_of? Object

どちらも誤りです。右、何もオブジェクトのインスタンスになることはできません。

そして

 Class.kind_of? Class
 Object.kind_of? Class

どちらも本当です

 Class.kind_of? Object
 Object.kind_of? Object

どちらも本当です

したがって、両方がまったく同じであるのに、なぜこれらの両方があるのでしょうか?

もう少し掘り下げた後、両方でサポートされているメソッドリストを返すこの簡単なメソッドを書きました

irb(main):054:0> def print_methods(obj)
irb(main):055:1>    obj.methods.each do |mm|
irb(main):056:2*        puts mm
irb(main):057:2>    end
irb(main):058:1> end

Print_methods(Object)とprint_methods(Class)のメソッドの違いのみが

     Nesting

ネストが継承を意味する場合、オブジェクトはシールクラスに似ていますか?

誰かが私にこれが何であるかを明確にできますか?

pdate: Eddsコメントへ

興味深いことに、メソッドリストには多くの違いがあります。

c=Class.new
print_methods(c)

o=Object.new
print_methods(o)

これで、クラスのインスタンスは実際にはクラスインスタンスであることがわかります(このクラスインスタンスは実際にはオブジェクトです)。オブジェクトインスタンスではありません。このインスタンスでさえ、別のインスタンスにまたがることができます

  xx = c.new //works - c is an Object / and xx is a instance of an Object c
  yy = o.new //nope  - o is already a instance of an Object, so it cannot be instantiated again

最後に、Objectは実際にはクラスのインスタンスです。なぜなら

  xx.is_a? Class 

は偽ですが、

  xx.is_a? Object 

trueを返します

私は正しいですか?

66
RameshVel

基本的に理解すべき重要なことは、すべてのクラスがClassクラスのインスタンスであり、すべてのクラスがObjectのサブクラスであることです(1.8では1.9では、すべてのクラスはBasicObjectのサブクラスです)。つまり、すべてのクラスは、Objectのサブクラスのインスタンスであるという意味でオブジェクトです。つまり、Classです。

もちろん、これはClassがそれ自体のインスタンスであることを意味します。それがあなたの脳を傷つけるなら、それについてあまり深く考えないでください。

ObjectおよびClassis_a? Objectです

x.is_a? yは、x.class == y or x.class < yの場合、つまりtrueのクラスがxである場合、またはyのクラスがxを継承している場合、yを返します。すべてのクラスはオブジェクトから継承するため、x.is_a? Objectxが何であってもtrueを返します。 (とにかく1.8では、1.9では、継承階層の最も基本的なクラスであるBasicObjectもあります)。

これらもis_a? Classです

ObjectClassはどちらも確かにクラスなので、驚くべきことではありません。

これらもinstance_of? Classですが、instance_of? Objectではありません。

is_a?とは異なり、x.instance_of? yは、x.class == yyのサブクラスである場合ではなく、x.classの場合にのみtrueを返します。したがって、xyはどちらもinstance_of? Classであるため、instance_of? Objectではありません。

右、何もオブジェクトのインスタンスになることはできません。

それは真実ではない。 Object.new.instance_of? Objectはtrueです。

やや?

kind_of?is_a?のエイリアスなので、上記を参照してください。

したがって、両方がまったく同じであるのに、なぜこれらの両方があるのでしょうか?

これまでのすべてがすべてのクラスに当てはまることを指摘しておく必要があります。例えば。上記と同じ理由で、String.is_a? ObjectString.is_a? ClassString.instance_of? Classはtrue、String.instance_of? Objectはfalseです。 (String.is_a? StringString.instance_of? Stringも同じ理由で両方ともfalseです-文字列は文字列ではなくクラスです)。

これから、すべてのクラスが同じであると結論付けることはできません。それらは同じクラスのすべてのインスタンスです。

メソッドの比較

ObjectClassはどちらもクラスなので、どちらもClassで定義されたすべてのインスタンスメソッドを持っています。 Classには、シングルトンメソッドnestingが追加されています。 nestingは、現在ネストされているモジュールを示します。継承とは関係ありません。

特定のクラスについて、TheClass.methodsは、Classによって定義されたインスタンスメソッドを返します(たとえば、superclassが継承するクラスを返すTheClass、およびnewの新しいインスタンスを作成するTheClass)と、そのクラスによって定義されたシングルトンメソッド。

とにかく、methodsは、特定のオブジェクトで直接呼び出すことができるメソッドを通知するだけです。クラスのインスタンスで呼び出すことができるメソッドはわかりません。そのためには、instance_methodsを使用できます。これは、ObjectClassで大きく異なる結果を返します。

38
sepp2k

Rubyでは、クラスとモジュールを含むすべてがObjectです。 Objectは最も低レベルのクラスです(まあ、Ruby 1.9.2にはBasicObjectもありますが、これは別の話です)。

次の出力を参照してください。

> Object.ancestors
# => [Object, Kernel, BasicObject] 
> Class.ancestors
# => [Class, Module, Object, Kernel, BasicObject] 
> Module.ancestors
# => [Module, Object, Kernel, BasicObject] 
> String.ancestors
# => [String, Comparable, Object, Kernel, BasicObject]

ご覧のとおり、ClassModuleはどちらもObjectを継承しています。

元のアサーションに戻ると、違いを理解する必要があります

  • is_a?
  • kind_of'
  • instance_of?

互換性はありません。 is_a?およびkind_of?は、otherが同じクラスまたは祖先である場合にtrueを返します。逆に、instance_of?は、otherが同じクラスである場合にのみtrueを返します。

> Class.is_a? Object
# => true 
> Class.kind_of? Object
# => true 
> Class.instance_of? Object
# => false 
18
Simone Carletti

クラス/メタクラスの階層は常に少し不可解です:)比較のためだけに Smalltalkの1つです ; Rubyでは、セットアップは同じ原則に基づいていますが、BehaviorClassDescriptionの区別がなく、考慮すべきモジュールと固有クラスがあります。

Smalltalkオブジェクトモデルの完全な説明は Pharo by Example にあり、これは 関連する質問 で指摘されています。

2
Damien Pollet

Ruby everythingのRameshはオブジェクトであり、Classも例外ではありません。

iRBでこれを試してください

Ruby-1.9.2-p136 :001 > o = Object.new
=> #<Object:0x000001020114b0> 
Ruby-1.9.2-p136 :002 > o.is_a? Class
=> false 
Ruby-1.9.2-p136 :003 > o.is_a? Object
=> true 

この例では、オブジェクトのインスタンスを作成し、それがクラス(false)かオブジェクト(true)かを確認しました。

Rubyのクラスは、そのクラスのインスタンスを作成するために使用されるある種のテンプレートオブジェクトです。これは明確ではありません。重要な概念は、RubyはJavaではなく純粋なオブジェクト指向言語であるということです。

2
Augusto

_whyが この記事 に書いているように

オブジェクトはメソッドを格納せず、クラスのみが格納できます。

最初の2つのセクションには、クラスとオブジェクトについていくつかの良い点があります。

1
Subtletree

答えの1つはこれについて言及しています:

基本的に理解すべき重要なことは、すべてのクラスはClassクラスのインスタンスであり、すべてのクラスはObjectのサブクラスであることです。したがって、すべてのクラスは、オブジェクトのサブクラス、つまりクラスのインスタンスであるという意味でオブジェクトです。

ちょっと頭がおかしい人には違う言葉で言いたいだけです。最初に自問してください。プログラミングのインスタンスは何ですか?プログラミングのサブクラスとは何ですか?インスタンスは、青写真(クラス)の単なる実現バリエーションです。サブクラスは、別のクラス(ブループリント)を継承するクラス(ブループリント)です。したがって、新しいクラスを作成すると、次のようになります。

class Apple
end

アップルはクラスのインスタンスです。つまり、ブループリントの実現されたバリエーションです。設計図を受け取り、詳細(メソッドと変数)を独自のバリエーションで埋めます。まあ、ブループリントは別のブループリントであるObjectを継承しています。したがって、すべてのクラスはObjectのサブクラスであるClassのインスタンスです。

class A 
end
A.parent  
=> Object     
A.class  
=> Class

注クラスの継承チェーンにはモジュールがあります(クラスの親がオブジェクトであるため、モジュールはミックスインとしてクラスに含まれていますか?)。

A.is_a?(Module)
 => true  

クラスAのインスタンス(A.new)には、Aの独自のバリエーションが実装されます。ただし、これらはオブジェクトインスタンスです。したがって、クラスインスタンス(例:クラスAの終了)とオブジェクトインスタンス(a = A.new)を区別する必要があります。オブジェクトインスタンスには、異なる継承チェーンがあります。これらは、クラスクラスのバリエーションではなく、クラスインスタンスブループリントの実現バリエーションです。

つまり、継承チェーンではクラスまたはモジュールではありません。しかし、他のオブジェクトインスタンスなので、Aにオブジェクトインスタンスがあり、Bにオブジェクトインスタンスがあり、AがBから継承する場合、Aの新しいオブジェクトインスタンスをインスタンス化すると、このインスタンスの継承チェーンにBインスタンスが含まれます。

RubyのすべてがObjectから継承されるため、これらはObjectからも継承されます。

a = A.new
 => #<A:0x007f966449b8d8> 
a.is_a?(Class)
 => false 
a.is_a?(Module)
 => false 
a.is_a?(Object)
 => true 

そして、これがすべてについて考える最良の方法です。考えを深めすぎないでください。これを私が書いたとおりに受け入れます。

1
Donato