有人能解释一下Class.superclass.class.superclass悖论吗?

30

这可能根本不是一个悖论,但对于新手来说,它看起来确实是这样。

> Class.superclass
=> Module
> Class.superclass.class
=> Class
> Class.superclass.class.superclass
=> Module

一个类的父类是模块,但模块本身也是一个类?

我该如何理解这个问题?


2
可能是类/对象悖论困惑的重复。另请参阅Ruby元类困惑 - Andrew Marshall
1
这些是非常好的参考资料。感谢你指出它们,安德鲁。 - Nathan
谢谢您指出! - Alex Onozor
2个回答

79
TL;DR: 模块是类的超类。模块是类的一个实例。
让我尝试更清晰地解释一下。请原谅我的手写图画-我没有任何花哨的绘图软件。

Ruby 中每个类都有一个超类*。

enter image description here

除了BasicObject,它没有超类。
阅读上面的图形如下:Float的超类是Numeric。 Numeric的超类是Object,依此类推...
当您实例化一个对象时,该对象将是某个类的实例。例如,“Nathan”是String类的一个实例。 “Joe”或“John”也是如此。 1是Fixnum类的一个实例,2、3、4等也是。

enter image description here

请阅读上方的图示:"Joe" 是 String 的一个实例,1 是 Fixnum 的一个实例,等等...
在 Ruby 中,与大多数其他编程语言不同的是,Class 只是另一个类,并且也可以像 Fixnum 或 String 一样被实例化。

enter image description here

请按照以下方式阅读上面的图表:0.01是Float的一个实例,String是Class的一个实例,以此类推...
请注意,Fixnum也是Class的一个实例,就像"Nathan"是String的一个实例一样。就像"John"是String的一个实例一样,Float也只是Class的一个实例。每个类都只是Class的一个实例,甚至Class本身也是如此!
每当您在应用程序中编写一个新类时,您只是实例化了一个新对象,其类是Class,就像Hash.new实例化了一个新的Hash,或者"Nathan"实例化了一个新的String。
# By running this, you will be instantiating a new Class, and 
# it will be named Post 
class Post < ActiveRecord::Base
end

# Here is another perfectly valid way to write the above code:
Post = Class.new(ActiveRecord::Base)

# you can even instantiate a Class without giving it an explicit name:
x = Class.new(ActiveRecord::Base)

# and since your new things are classes, they can be instantiated
obj1 = Post.new
obj2 = x.new

此外,“模块”只是“类”的另一个实例。每当您在应用程序中编写新模块时,都只是实例化一个新模块。
# this will instantiate a new Module, and assign it to Foo
module Foo
end

# Here is another perfectly valid way to write the above code:
Foo = Module.new

# you can even instantiate a Module without giving it an explicit name.
m = Module.new

一个旁注:模块只是方法和常量的集合。类也是方法和常量的集合,但具有可以实例化的附加功能。模块无法被实例化。也就是说,m.new 不起作用。
因此,回到顶部的图形,您的问题可以直接回答:

所以类的父类是模块,但模块是一个类?

您可以从顶部的图形中看到:模块是类的超类。
从底部的图形中可以看出:模块是类的一个实例。

哇,非常有帮助。我把选定的答案改成了这个,尽管你提供的两个答案都对我有所帮助。 - Nathan
这个话题值得展开全面的讨论,其中有很多分支——不幸的是,Stack Overflow没有提供这种类型的良好论坛。但最终,我的结论是Object和Class之间存在一些循环逻辑。从一个外行人的角度(我只编程了大约5个月),我的看法是,由于Ruby是用C实现的,所以也在C中被实例化。而在这个实例化过程中就声明了循环逻辑。我希望我的理解是正确的。 - Nathan
1
@@Nathan 你可以从上面的图中看到:Module是Class的超类。从下面的图中可以看出:Module是Class的一个实例。因此,它们之间是循环的关系。我想这是一个重要的观点。 - SamFlushing
1
当我在Ruby中通过输入class Foo然后在下一行输入end来创建一个类时,当我执行Foo.superclass时,我看到的是"Object"而不是"Module"。为什么会这样呢?根据上面的图表,Class的超类是Module对吧?但是当我运行代码时却没有看到这个结果。 - Jwan622
@Jwan622 当你创建一个类时,它的超类默认为Object,除非你指定另一个。因此,Foo的超类是ObjectFooClass的一个实例,而Class的超类是Module - John Douthat

15

在您的第二个示例中,Class.superclass.class 调用了 Module.class。Module 是指一个类,即 模块(Module)类。

AnyClass.superclass.class 将返回 Class,除了 BasicObject.superclass.class

类与实例之间的区别很重要。BasicObject 是一个类。它是一个扩展了 nil 的类,这是说它没有超类的一种高级方式。它是树的根。 EVERYTHING 是一个对象,这又是说,所有东西都是某个类的实例。

字符串(String)示例

"Nathan" is an object.
"Nathan" is an instance of the String class.
"Nathan" is not a class.
"Nathan" has no superclass, because "Nathan" is not a class.

String is an object.
String is an instance of the Class class.
String's superclass is Object.

Object is an object.
Object is an instance of the Class class.
Object's superclass is BasicObject.

BasicObject is an object.
BasicObject is an instance of the Class class
BasicObject's superclass is nil.

nil is an object.
nil is an instance of the NilClass class
nil has no superclass, because it is not a class.

Fixnum示例

1 is an object.
1 is an instance of the Fixnum class.
1 is not a class.
1 has no superclass, because it is not a class.

Fixnum is an object.
Fixnum is an instance of the Class class.
Fixnum's superclass is Integer.

Integer is an object.
Integer is an instance of the Class class
Integer's superclass is Numeric.

Numeric is an object.
Numeric is an instance of the Class class.
Numeric's superclass is Object.

# everything below here is in the above example.
Object is an object.
Object is an instance of the Class class.
Object's superclass is BasicObject.

BasicObject is an object.
BasicObject is an instance of the Class class
BasicObject's superclass is nil.

nil is an object.
nil is an instance of the NilClass class
nil has no superclass, because it is not a class.
所以,最终:
Class is an object.
Class is an instance of the Class class. # this is probably the most important part.
Class's superclass is Module # 2nd most important part

Module is an object
Module is an instance of the Class class. # 3rd
Module's superclass is Object # 4th

# everything below here is in the above examples.
Object is an object.
Object is an instance of the Class class.
Object's superclass is BasicObject.

BasicObject is an object.
BasicObject is an instance of the Class class
BasicObject's superclass is nil.

nil is an object.
nil is an instance of the NilClass class
nil has no superclass, because it is not a class.

表格形式如下:

enter image description here

如果您想验证它是否全部正确,只需在Ruby中运行即可。

"Nathan".is_a?(BasicObject) # => true    "Nathan" is an object.
"Nathan".class #=> String                "Nathan" is an instance of the String class.
"Nathan".is_a?(Class) #=> false          "Nathan" is not a class.
"Nathan".superclass # NoMethodError      "Nathan" has no superclass, because "Nathan" is not a class.

String.is_a?(BasicObject) #=> true       String is an object.
String.class #=> Class                   String is an instance of the Class class.
String.superclass #=> Object             String's superclass is Object.

Object.is_a?(BasicObject) #=> true       Object is an object.
Object.class #=> Class                   Object is an instance of the Class class.
Object.superclass #=> BasicObject        Object's superclass is BasicObject.

BasicObject.is_a?(BasicObject) #=> true  BasicObject is an object.
BasicObject.class #=> Class              BasicObject is an instance of the Class class
BasicObject.superclass #=> nil           BasicObject's superclass is nil.

nil.is_a?(BasicObject) #=> true          nil is an object.
nil.class #=> NilClass                   nil is an instance of the NilClass class
nil.superclass # NoMethodError           nil has no superclass, because it is not a class.

并且从 Class 开始:

Class.is_a?(BasicObject) #=> true        Class is an object.
Class.class #=> Class                    Class is an instance of the Class class. # this is probably the most important part.
Class.superclass #=> Module              Class's superclass is Module # 2nd most important part

Module.is_a?(BasicObject) #=> true       Module is an object
Module.class #=> Class                   Module is an instance of the Class class. # 3rd
Module.superclass #=> Object             Module's superclass is Object # 4th

Object.is_a?(BasicObject) #=> true       Object is an object.
Object.class #=> Class                   Object is an instance of the Class class.
Object.superclass #=> BasicObject        Object's superclass is BasicObject.

BasicObject.is_a?(BasicObject) #=> true  BasicObject is an object.
BasicObject.class #=> Class              BasicObject is an instance of the Class class
BasicObject.superclass #=> nil           BasicObject's superclass is nil.

nil.is_a?(BasicObject) #=> true          nil is an object.
nil.class #=> NilClass                   nil is an instance of the NilClass class
nil.superclass # NoMethodError           nil has no superclass, because it is not a class.

也许让我困惑的是,每个人都说一切都是对象,但当我执行BasicObject.class时,它返回Class。所以我对如何理解“类”感到困惑。如果BasicObject的类是Class,那么一切不是真正的对象,而是类吗? - Nathan
哈哈,这开始感觉像是哲学101,亚里士多德的不动之动和诸如此类的东西。所以如果一切都是对象(类的实例),那么BasicObject呢?BasicObject.class => Class。Class.class => Class。然而,当你向上追溯到nil时,你会得到nil.class => NilClass,而NilClass.class => Class。所以如果一切都是对象(类的实例),那么一切实例化的初始类是什么 - 它是如何产生的? - Nathan
所以除了nil和你自己定制的对象之外,所有东西都是Class类的实例,包括Class本身。此外,还有一个名为Module的类,其超类是Object。Module是Class的超类。这意味着Object是Class的超级父类。听起来没错吧?如果是的话,那么唯一需要考虑的就是Object如何成为Class的实例,而Class(通过Module)又是Object的子类? - Nathan
顺便说一句,非常感谢您的帮助和解释。我的大脑总是觉得递归、反转等等这些东西有点尴尬。我想有些人可能更容易理解,但想以这种方式思考对每个人来说都有点奇怪吧。无论如何,再次感谢。 - Nathan
所有的类都是对象,但并非所有的对象都是类。没问题。希望这能对你有所帮助。也许会有人来解释得比我更清楚。 - John Douthat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接