【问题标题】:Ruby craziness: Class vs Object?Ruby 疯狂:类与对象?
【发布时间】:2011-02-11 09:45:11
【问题描述】:

我刚开始玩 JRuby。这是我的第一篇红宝石帖子。我很难理解 Ruby 中的类和对象。这并不意味着像其他面向对象语言中的类和对象。举个例子

Class.is_a? Object

返回

Object.is_a? Object

所以类和对象都是对象

又来了一个

Class.is_a? Class

返回

Object.is_a? Class

等等,我还没写完

 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

如果Nesting是继承的意思,Object是不是类似于密封类??

有人能帮我解释一下这是什么吗?

更新:致 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 是一个 Class 的实例。因为

  xx.is_a? Class 

是假的,但是

  xx.is_a? Object 

返回真

我说的对吗??

【问题讨论】:

  • +1:良好的演绎技巧
  • 我可以衷心推荐这个话题的镐处理:ruby-doc.org/docs/ProgrammingRuby/html/classes.html
  • @Edd,谢谢伙计..会检查.. :)
  • 还值得注意的是,到目前为止,您的挖掘已经查看了 Object 和 Class 的类方法,它们相似,但在实例方法上没有。 Class 的实例有一堆 Object 的实例没有的方法。如果您遇到简洁的解释,听到它会很有趣!
  • @Edd,我已经更新了我的帖子,请查看..

标签: ruby class object


【解决方案1】:

基本上要理解的关键是每个类都是Class 类的一个实例,每个类都是Object 的子类(在1.8 中-在1.9 中,每个类都是BasicObject 的子类)。所以每个类都是一个对象,因为它是Object 的子类的一个实例,即Class

当然这意味着Class 是它自己的一个实例。如果这让你的大脑受伤,那就别想得太深了。

ObjectClassis_a? Object

x.is_a? y 如果x.class == y or x.class < y 则返回true,即如果x 的类是yx 的类继承自y。因为每个类都继承自对象x.is_a? Object,所以无论x 是什么,都返回true。 (无论如何,在 1.8 中,在 1.9 中还有 BasicObject,它现在是继承层次结构中最基本的类)。

他们也是is_a? Class

ObjectClass 确实是类,所以这不足为奇。

他们也是instance_of? Class,但不是instance_of? Object

is_a? 不同,x.instance_of? y 仅在 x.class == y 时返回 true,而不是在 x.classy 的子类时返回。所以由于xy 都是instance_of? Class,所以它们不是instance_of? Object

对,没有什么可以是对象的实例。

那不是真的。 Object.new.instance_of? Object 是真的。

kind_of?

kind_of?is_a? 的别名,见上文。

所以两者完全一样,那为什么我们同时拥有这两个呢?

应该指出,到目前为止,所有类都适用。例如。 String.is_a? ObjectString.is_a? ClassString.instance_of? Class 为真,String.instance_of? Object 为假,原因同上。 (还有String.is_a? StringString.instance_of? String 都是假的,原因相同——String 是一个类,而不是一个字符串)。

你不能由此断定所有的类都是一样的。它们只是同一类的所有实例。

比较方法

由于ObjectClass 都是类,它们都具有Class 定义的所有实例方法。 Class 还具有单例方法nestingnesting 告诉你当前嵌套在哪个模块中,它与继承无关。

对于任何给定的类TheClass.methods 将返回由Class 定义的实例方法(例如superclass,它返回TheClass 继承自的类,new 创建TheClass 的新实例) 加上该类定义的单例方法。

无论如何methods 只告诉您可以在给定对象上直接调用哪些方法。它不会告诉您可以在类的实例上调用哪些方法。为此,您可以使用instance_methods,它为ObjectClass 返回明显不同的结果。

【讨论】:

  • 感谢您的详细解释....我刚开始使用 JRuby 一周,就已经深深爱上了....
【解决方案2】:

在 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 

【讨论】:

  • 这绝对比我的回答好:)
  • 这是一个很好的答案,但并不能完全解释为什么Object.instance_of? Class 是正确的。我想是因为Object是object的常量类定义,Class是class的常量类定义,所以都是Class的实例。我还是不太清楚。
  • 谢谢 :) 尽管它们组合起来有点令人惊讶,但它们各自都非常有意义。 +1。
【解决方案3】:

其中一个答案提到了这一点:

基本上要理解的关键是每个类都是 Class 类的实例,每个类都是 Object 的子类。 所以每个类都是一个对象,因为它是一个实例的一个实例 Object的子类,即Class。

我只是想为那些有点脑筋急转弯的人换个说法。首先问自己:编程中的实例是什么?什么是编程中的子类?实例只是蓝图(类)的已实现变体。子类只是从另一个类(蓝图)继承的类(蓝图)。所以当你创建一个新类时:

class Apple
end

Apple 是 Class 的一个实例,也就是说,它是蓝图的实现变体。它采用蓝图并用自己的变体填充细节(方法和变量)。好吧,蓝图继承自另一个蓝图,即 Object。所以每个类都是Class的一个实例,Class是Object的一个子类。

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

注意类在其继承链中具有模块(模块作为混合包含在类中,也许是因为类的父对象是对象?)。

A.is_a?(Module)
 => true  

类 A 的实例 (A.new) 将有自己实现的 A 变体。但它们是对象实例。所以我们必须区分类实例(例如A类结束)和对象实例(a = A.new)。对象实例具有不同的继承链。它们是类实例蓝图的实现变体,而不是类 Class 的变体。

这意味着在它们的继承链中不是 Class 或 Module。而是其他对象实例,所以如果 A 有对象实例,B 有对象实例,并且 A 继承自 B,当我们实例化 A 的新对象实例时,这个实例的继承链中会有 B 实例。

它们也将继承自 Object,因为 Ruby 中的所有内容都继承自 Object。

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

这是思考这一切的最佳方式。不要深入思考。接受我写的这个。

【讨论】:

    【解决方案4】:

    Ramesh,在 ruby​​ 中一切都是对象,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 
    

    在本例中,我创建了一个 Object 的实例,并检查它是类 (false) 还是 Object (true)。

    ruby 中的类,是某种模板对象,用于创建该类的实例。抱歉,这不是很清楚。关键概念是 ruby​​ 是一种纯面向对象的语言,而不是 Java。

    【讨论】:

      【解决方案5】:

      类/元类层次结构总是有点令人费解:) 只是为了比较,here's the one in Smalltalk;在 Ruby 中,设置基于相同的原则,只是它没有 BehaviorClassDescription 区别,并且需要考虑模块和特征类。

      Pharo by Example 中提供了 Smalltalk 对象模型的完整说明,正如 related question 所指出的那样。

      【讨论】:

        【解决方案6】:

        正如_why在this article中所写的那样

        对象不存储方法,只有类可以。

        前几节有一些关于类与对象的优点

        【讨论】:

          【解决方案7】:

          将类视为全局对象。

          【讨论】:

            猜你喜欢
            • 2011-01-27
            • 1970-01-01
            • 1970-01-01
            • 2012-06-08
            • 2022-11-16
            • 2010-12-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多