2012-05-11 24 views
28

Probablemente no sea una paradoja en absoluto, pero desde la perspectiva de los novatos, seguramente parece ser así.¿Alguien puede explicar la paradoja Class.superclass.class.superclass?

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

Entonces, el elemento primario de una clase es el módulo, pero el módulo es una clase?

¿Cómo puedo darle sentido a esto?

+2

Posible duplicado de [La clase/confusión de paradoja de objeto] (http://stackoverflow.com/questions/7675774/the-class-object-paradox-confusion). Consulte también [Confusión de metaclase de Ruby] (http://stackoverflow.com/questions/10525053/ruby-metaclass-confusion). –

+1

Estas son excelentes referencias. Gracias por señalarlos, Andrew. – Nathan

+0

¡Gracias por señalar! –

Respuesta

71

TL; DR: Módulo es la superclase de Clase. El módulo es una instancia de Clase.


Déjame intentar explicarlo más claramente. Por favor perdone mis dibujos escritos a mano. No tengo ningún software de dibujo elegante.

Todas las clases en Ruby tienen 1 superclase *.

enter image description here

* A excepción de BasicObject, que no tiene una superclase.

Lea el gráfico anterior de esta manera: La superclase de Float es numérica. La superclase de Numeric es Object, etc ...

Cuando crea una instancia de un objeto, el objeto será una instancia de alguna clase. Por ejemplo, "Nathan" es una instancia de la clase String. También lo es "Joe" o "John". 1 es una instancia de la clase Fixnum, al igual que 2, 3, 4, etc ...

enter image description here

Leer el gráfico anterior así: "Joe" es una instancia de cadena. 1 es una instancia de Fixnum, etc ...

Bueno, en Ruby, a diferencia de la mayoría de los otros idiomas, Class es una clase más y también se puede instanciar, como Fixnum o String.

enter image description here

Leer el gráfico anterior como esto: 0,01 es una instancia de Float. String es una instancia de Class, etc ...

Date cuenta de que Fixnum es una instancia de Class, al igual que "Nathan" es una instancia de String. Al igual que "John" es una instancia de String, Float es solo una instancia de Class. ¡Cada clase es solo una instancia de Clase, incluso la Clase misma!

Cada vez que escribe una nueva clase en su aplicación, solo está instanciando un nuevo objeto cuya clase es Clase, al igual que Hash.new crea una nueva Hash o "Nathan" crea una nueva cadena.

# 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 

Además, el módulo es simplemente otra instancia de la clase. Cada vez que escribe un nuevo módulo en su aplicación, solo está creando un nuevo Módulo.

# 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 

Un aparte: Un módulo es solo una colección de métodos y constantes. Las clases también son una colección de métodos y constantes, pero con la funcionalidad adicional de poder crear instancias. Un módulo no puede ser instanciado. Es decir, m.new no funcionará.

Así, refiriéndose de nuevo a la gráfica superior, su pregunta se puede responder directamente:

Así matriz de una clase es el módulo, pero es un módulo de clase?

Se puede ver en el gráfico superior: Módulo es la superclase de la clase.

Desde el gráfico inferior: Módulo es una instancia de Clase.

+0

Guau, muy útil. Cambié la respuesta elegida a esta, aunque las dos respuestas que me proporcionó me ayudaron. – Nathan

+0

Este tema merece una discusión completa, que tiene muchas tangentes, desafortunadamente Stack Overflow no brinda un buen foro para ese tipo de cosas. Sin embargo, al final, mi conclusión es que hay una lógica circular que ocurre entre Objeto y Clase. Desde la perspectiva de un profano (he estado programando durante ~ 5 meses), mi opinión es que, dado que Ruby se implementa en C, también se ejemplifica en C. Y durante esta instanciación es donde se declara la lógica circular. Espero estar en el camino correcto con eso. – Nathan

+1

@@ Nathan Puede ver en el gráfico superior: Módulo es la clase superior de clase. Desde el gráfico inferior: Módulo es una instancia de clase. ** Así que eso funciona de forma circular **. Creo que ese es el punto importante – SamFlushing

15

En el segundo ejemplo Class.superclass.class, que está llamando módulo.clase. El módulo se refiere a una clase, la clase Módulo.

AnyClass.superclass.class volverá clase, a excepción de BasicObject.superclass.class

La distinción entre una clase y una instancia es importante. BasicObject es una clase. Es una clase que se extiende nil, que es una forma elegante de decir que no tiene superclase. Es la raíz del árbol. TODO es un objeto, que es otra forma de decir que todo es una instancia de alguna clase.

String Ejemplo

"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 ejemplo

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. 

Así que, finalmente:

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. 

en forma de tabla:

enter image description here

Y si le gustaría para verificar que todo es verdad, sólo puede ejecutarlo en 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. 

Y a partir de Clase:

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. 
+0

Quizás lo que me confunde es que todo el mundo sigue diciendo que todo es un objeto, pero cuando hago BasicObject.class, devuelve Class. Entonces estoy confundido acerca de cómo entender qué es una "clase". Si la clase de BasicObject es Class, entonces, ¿no es todo realmente una clase, en lugar de un objeto? – Nathan

+0

Lol, esto empieza a sentirse como la filosofía 101, el motor inmóvil de Aristóteles y todo eso. Entonces, si todo es un objeto (una instancia de una clase), ¿qué pasa con BasicObject? BasicObject.class => Class. Class.class => Clase. Sin embargo, cuando sube la cadena a cero, obtiene nil.class => NilClass y NilClass.clase => Clase. Entonces, si todo es un objeto (una instancia de una clase), entonces, ¿cuál es la clase inicial de la que todo lo que se crea una instancia - y cómo surge? – Nathan

+0

Entonces, con la excepción de 'nil' y sus propios objetos personalizados, todo es una instancia de la clase Class, incluida Class. Además, hay una clase llamada Module, cuya superclase es Object. El módulo es la superclase de clase. Lo que significa que Object es la clase super-duper de Class. ¿Eso suena bien? Si es así, entonces lo único que queda es reflexionar: ¿cómo puede Object ser una instancia de Class, pero Class (a través de Module) es un elemento secundario de Object? – Nathan

Cuestiones relacionadas