Pregunta ¿Puede alguien explicar la paradoja Class.superclass.class.superclass?


Probablemente no sea una paradoja en absoluto, pero desde la perspectiva de los novatos, seguramente parece ser así.

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

¿Entonces el padre de una clase es un módulo, pero el módulo es una clase?

¿Cómo puedo darle sentido a esto?


28
2018-05-11 20:55


origen


Respuestas:


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.

Cada clase en Ruby tiene 1 superclase *.

enter image description here

* Excepto para BasicObject, que no tiene una superclase.

Lea el gráfico anterior de la siguiente 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

Lea el gráfico anterior de esta manera: "Joe" es una instancia de String. 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

Lea el gráfico anterior de esta manera: 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, como Hash. New instancia un nuevo 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, Module es solo otra instancia de Class. 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 trabajará.

Entonces, volviendo al gráfico superior, su pregunta puede responderse directamente:

¿Entonces el padre de una clase es un módulo, pero el módulo es una clase?

Puede ver desde el gráfico superior: Módulo es la superclase de Clase.

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


71
2018-05-12 03:57



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

AnyClass.superclass.class devolverá la Clase, excepto 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.

Ejemplo de cadena

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

Ejemplo de 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.

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 desea verificar que todo sea cierto, 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 comenzando desde la 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.

15