Locura Ruby: ¿Clase vs objeto?

Acabo de empezar a jugar con JRuby. Este es mi primer post Ruby. Me costó entender las clases y los objetos en Ruby. No significa como clases y objetos en otros idiomas orientados a objetos. para un ejemplo

Class.is_a? Object 

devuelve verdadero y

 Object.is_a? Object 

tambien

así que clase y objeto son ambos objetos

aquí viene otro

 Class.is_a? Class 

devuelve verdadero y

 Object.is_a? Class 

tambien

espera, no he terminado todavía

  Object.instance_of? Class Class.instance_of? Class 

Ambos son verdad

  Object.instance_of? Object Class.instance_of? Object 

Ambos son falsos bien, nada puede ser instancia de objeto.

Y

  Class.kind_of? Class Object.kind_of? Class 

ambos son verdad

  Class.kind_of? Object Object.kind_of? Object 

ambos son verdad

Entonces, ambos son exactamente iguales, entonces ¿por qué tenemos ambos esto?

Después de algunas excavaciones más, escribí este método simple para devolver la lista de métodos soportada por ambos

 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 

La única diferencia de método entre print_methods (Object) y print_methods (Class) es

  Nesting 

si Anidar significa herencia, ¿el Objeto es similar a la clase sellada?

¿Puede alguien aclararme qué es todo esto?

Actualización: A Edds comentar

Curiosamente veo muchas diferencias en la lista de métodos en

 c=Class.new print_methods(c) 

Y

 o=Object.new print_methods(o) 

Ahora entiendo que la instancia de una clase es realmente una instancia de clase (y esta instancia de clase es en realidad un objeto) no una instancia de objeto. E incluso esta instancia me permite abarcar otras instancias.

  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 

Así que finalmente, el objeto es realmente una instancia de una clase. Porque

  xx.is_a? Class 

es falso, pero

  xx.is_a? Object 

devuelve verdadero

Estoy en lo cierto ??

Básicamente, la clave a entender es que cada clase es una instancia de la clase y cada clase es una subclase de Object (en 1.8 – en 1.9 cada clase es una subclase de BasicObject ). Así que cada clase es un objeto en el sentido de que es una instancia de una subclase de Object , es decir, Class .

Por supuesto, esto significa que la Class es una instancia de sí misma. Si eso hace que te duela el cerebro, no lo pienses demasiado.

Object y Class son is_a? Object is_a? Object

x.is_a? y x.is_a? y devuelve true si x.class == y or x.class < y , es decir, si la clase de x es y o la clase de x hereda de y . Dado que cada clase hereda del objeto x.is_a? Object x.is_a? Object devuelve verdadero sin importar lo que sea x . (De todos modos, en 1.8, en 1.9 también está BasicObject que ahora es la clase más básica en la jerarquía de herencia).

También son is_a? Class is_a? Class

Tanto el Object como la Class son clases, por lo que no debería ser sorprendente.

¿También son de instance_of? Class instance_of? Class , pero no instance_of? Object instance_of? Object

A diferencia de is_a? , x.instance_of? y x.instance_of? y solo devuelve verdadero si x.class == y , no si x.class es una subclase de y . Entonces, ¿ya que tanto x como y son instance_of? Class instance_of? Class , no son de instance_of? Object instance_of? Object

bien, nada puede ser instancia de objeto.

Eso no es cierto. Object.new.instance_of? Object Object.new.instance_of? Object es verdadero.

¿mas o menos?

kind_of? es un alias para is_a? , así que ver más arriba.

Entonces, ambos son exactamente iguales, entonces ¿por qué tenemos ambos esto?

Cabe señalar que hasta ahora todo es cierto para todas las clases. Ej. String.is_a? Object String.is_a? Object , String.is_a? Class String.is_a? Class y String.instance_of? Class String.instance_of? Class son verdaderas y String.instance_of? Object String.instance_of? Object es falso por las mismas razones que arriba. (También String.is_a? String y String.instance_of? String son falsos por las mismas razones: String es una clase, no una cadena).

No se puede concluir de esto que todas las clases son iguales. Son solo todas las instancias de la misma clase.

Métodos de comparación

Dado que tanto el Object como la Class son clases, ambos tienen todos los métodos de instancia definidos por la Class . Class adicionalmente tiene el método de nesting singleton. nesting le indica en qué módulo está nested actualmente, no tiene nada que ver con la herencia.

Para cualquier clase dada, TheClass.methods devolverá los métodos de instancia definidos por Class (por ejemplo, superclass , que devuelve la clase de la cual TheClass hereda, y new que crea una nueva instancia de TheClass ) más los métodos singleton definidos por esa clase.

De todos modos, los methods solo le dicen qué métodos se pueden llamar directamente en un objeto determinado. No le dice qué métodos se pueden llamar en una instancia de una clase. Para eso, puede usar instance_methods , que devuelve resultados significativamente diferentes para Object y Class .

En Ruby, todo es un Object incluyendo clases y módulos. Object es la clase más baja (bueno, en Ruby 1.9.2 también hay BasicObject pero esta es otra historia).

Vea la siguiente salida.

 > 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] 

Como puede ver, tanto la Class como el Module heredan de Object .

De vuelta a sus afirmaciones originales, usted tiene que entender la diferencia entre

  • is_a?
  • kind_of'
  • instance_of?

No son intercambiables. is_a? y kind_of? devuelve true si otro es la misma clase o un antepasado. A la inversa, instance_of? devuelve true solo si otro es la misma clase.

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

Ramesh, en ruby todo es un objeto, y una clase no es una excepción.

prueba esto en irb

 ruby-1.9.2-p136 :001 > o = Object.new => # ruby-1.9.2-p136 :002 > o.is_a? Class => false ruby-1.9.2-p136 :003 > o.is_a? Object => true 

en este caso, he creado una instancia de un objeto y he comprobado si es una clase (falsa) o un objeto (verdadera).

Una clase en ruby ​​es un tipo de objeto de plantilla que se utiliza para crear instancias de esa clase. Siento que esto no esté super claro. El concepto clave es que ruby ​​es un lenguaje orientado a objetos puros, a diferencia de Java.

La jerarquía de clase / metaclase es siempre un poco desconcertante 🙂 Solo para comparación, aquí está la de Smalltalk ; en Ruby, la configuración se basa en los mismos principios, excepto que no tiene las distinciones de Behavior y ClassDescription , y hay módulos y eigenclasses para tener en cuenta.

Una explicación completa del modelo de objetos Smalltalk está disponible en Pharo por Ejemplo , como se señala en esta pregunta relacionada .

Como _por qué escribe en este artículo.

Los objetos no almacenan métodos, solo las clases pueden.

Las primeras secciones de pareja tienen algunos puntos positivos sobre las clases y los objetos.

Una de las respuestas menciona esto:

Básicamente, la clave a entender es que cada clase es una instancia de la clase y cada clase es una subclase de Object. Así que cada clase es un objeto en el sentido de que es una instancia de una subclase de Objeto, es decir, Clase.

Solo quiero expresslo de manera diferente para aquellos que tienen un pequeño giro cerebral. Primero pregúntate: ¿Qué es una instancia en la progtwigción? ¿Y qué es una subclase en progtwigción? Una instancia es solo una variación realizada de un plano (la Clase). Una subclase es simplemente una clase (modelo) que se hereda de otra clase (modelo). Entonces cuando creas una nueva clase:

 class Apple end 

Apple es una instancia de Clase, es decir, es una variación realizada del plano. Toma el plano y completa los detalles (métodos y variables) con su propia variación. Bueno, el plano se hereda de otro plano, que es Objeto. Así que cada clase es una instancia de Clase, que es una subclase de Objeto.

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

Note: La clase tiene el módulo en su cadena de herencia (¿el módulo incluido en la clase como una combinación tal vez porque el padre de la clase es Object?).

 A.is_a?(Module) => true 

Las instancias (A.new) de la clase A tendrán sus propias variaciones realizadas de A. Pero son instancias de objetos. Por lo tanto, debemos distinguir instancias de clase (por ejemplo, final de clase A) e instancias de objeto (a = A.nuevo). Las instancias de objetos tienen una cadena de herencia diferente. Son una variación realizada de un modelo de instancia de clase, no una variación de clase de clase.

Esto significa que en su cadena de herencia no es Clase o Módulo. Pero más bien otras instancias de objeto, así que si A tiene instancias de objeto y B tiene instancias de objeto y A hereda de B, cuando instanciamos una nueva instancia de objeto de A, esta instancia tendrá instancias de B en su cadena de herencia.

También heredarán de Object, ya que todo en Ruby hereda de Object.

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

Y esta es la mejor manera de pensar en todo. No profundices demasiado con tu pensamiento. Acepta esto como lo he escrito.

Piense en las clases como objetos globales.