Método ===

¿Alguien me puede explicar porqué me pasa esto?:

u = User.find 24
=> #<User:0x3ead8c8…
u === User
=> false
User === u
=> true


David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

On Feb 15, 2007, at 12:15 PM, David A. wrote:

¿Alguien me puede explicar porqué me pasa esto?:

u = User.find 24
=> #<User:0x3ead8c8…

u === User
=> false

User === u
=> true

Ese operador no es conmutativo.

User === u

se traduce en

User.===(u)

por lo que se esta ejecutando el metodo de clase ===. Si User no lo
ha redefinido hereda el de Module, que dice si u es instancia o no de
User (lo es).

En cambio

u === User

ejecuta u.===(User), que si no lo ha redefinido pilla el de Object,
que es equivalente a Object#==. Como u y User son objetos distintos,
devuelve false.

– fxn

El Thursday 15 February 2007 11:15:59 David A.
escribió:>

=> true

En el primer caso, estás invocando al método === del objeto ‘u’; en el
segundo, estás invocando al método === el objeto ‘User’ (que es una clase).
En el primer caso, será verdadero si ‘u’ y ‘User’ son iguales (que no es
el
caso). En el segundo caso, será verdadero si ‘u’ es de la clase ‘User’
(algo
que es cierto).

El método ‘===’ es una de esas cosas de Ruby que me encantan. Se trata de
un
método de Object que cada descendiente (Object es la clase ‘padre’ de
todas
las clases en Ruby) redefine según tenga sentido para ella. Object#== y
Object#=== son equivalentes.

Pero por ejemplo, en el caso de Range#=== se comporta como
Range#member?; es
decir, será verdadero si el objeto que le pasamos como parámetro se
encuentra
dentro del rango en
cuestión.
Esto le da un nuevo sentido a la estructura ‘case’, ya que es
precisamente
este método el que se utiliza a la hora de comparar:

case 79
when 1…50 then print “low\n”
when 51…75 then print “medium\n”
when 76…100 then print “high\n”
end

En este ejemplo de la documentación, el resultado será “high”, ya que lo que
hace es invocar a (1…50) === 79, (51…75) === 79 y (76…100) === 79.

Y en este caso, ¿cuál será el resultado? Lo dejo como ejercicio, aunque es
muy
facilito.

cadena = “una cadena”
case cadena
when String then print “clase”
when “una cadena” then print “cadena”
end

Saludos.


Imobach González Sosa
Servicio de Informática y Comunicaciones
Universidad de Las Palmas de Gran Canaria
Teléfono: +34 928457067
Correo-e: igonzalezs en pas.ulpgc.es

Imobach González Sosa
correo-e: imobachgs en banot punto net
jabber id: osoh en jabberes punto org
web: banot.net
blog: http://devnull.blogs.banot.net/

David A. wrote:

¿Alguien me puede explicar porqué me pasa esto?:

u === User

=> false

User === u

=> true

Primero para fijar el tiro, esto no viene causado por Rails sino por
Ruby, y te daría lo mismo si haces la prueba con una clase estándar, tal
que String.

En el primer caso estás invocando al === de Object, que te da cierto
básicamente si los dos objetos son el mismo (salvo sobrecargas en
subclases)

En el segundo caso invocas al === de Module, que te da cierto en el caso
de que el objeto de la derecha sea de la misma clase o haya heredado de
ésta. Precisamente está sobrecargado para permitir usar en un case la
comparación “es una instancia de”

Saludos,

javier ramirez

En el primer caso estás invocando al === de Object, que te da cierto
básicamente si los dos objetos son el mismo (salvo sobrecargas en
subclases)
por si he “malguiado” a alguien con mi deformación profesional, en Ruby
no se sobrecargan los métodos.

Una vez reescrito un método, independientemente de que la signatura sea
diferente por el tipo de los parámetros, ya he perdido el método
original de esa clase (a no ser que previamente haga un alias, y siempre
teniendo disponible el método si lo hubiera de la clase padre mediante
super)

gracias por el toque fxn :wink:


Estamos de estreno… si necesitas llevar el control de tus gastos
visita http://www.gastosgem.com !!Es gratis!!

On 2/15/07, Xavier N. [email protected] wrote:

ejecuta u.===(User), que si no lo ha redefinido pilla el de Object,
que es equivalente a Object#==. Como u y User son objetos distintos,
devuelve false.

Muchas gracias Xavier,

¿Debería redefinir entonces === en la clase User o me replanteo la
forma de hacer las cosas?


David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

On 2/15/07, Imobach González Sosa [email protected] wrote:

El método ‘===’ es una de esas cosas de Ruby que me encantan. Se trata de un
método de Object que cada descendiente (Object es la clase ‘padre’ de todas
las clases en Ruby) redefine según tenga sentido para ella. Object#== y
Object#=== son equivalentes.

Gracias :slight_smile:

Lo que no entiendo muy bien es porqué Object#=== es lo mismo que
Object#== ¿no sería mejor que Object#=== comprobara si el parámetro y
el objeto son de la misma clase? (supongo que hay una razón, pero no
la veo ahora mismo)

Un saludo

David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

On Feb 15, 2007, at 1:21 PM, David A. wrote:

On 2/15/07, Xavier N. [email protected] wrote:

ejecuta u.===(User), que si no lo ha redefinido pilla el de Object,
que es equivalente a Object#==. Como u y User son objetos distintos,
devuelve false.

Muchas gracias Xavier,

¿Debería redefinir entonces === en la clase User o me replanteo la
forma de hacer las cosas?

=== esta pensado para ser usado en las clausulas when de los case
statements (ni idea de como decir “statement” en castellano). Como
sabes Ruby lo usa alli transparentemente, por ello === no suele
invocarse directamente. Habria que redefenirlo o no en funcion de eso.

– fxn

On 2/15/07, Xavier N. [email protected] wrote:

=== esta pensado para ser usado en las clausulas when de los case
statements (ni idea de como decir “statement” en castellano). Como
sabes Ruby lo usa alli transparentemente, por ello === no suele
invocarse directamente. Habria que redefenirlo o no en funcion de eso.

Me parece estupenda esa característica de Ruby, el único problema es
cuando, por temas de namespaces, no puedo acceder a una clase desde un
módulo (es decir, no puedo hacer un case para comprobar la clase
porque User no existe en el módulo que estoy haciendo).

Pensé en hacer algo tal que
así:
def ===(objeto)
self.class == objeto.class || self.class == objeto ||
self.class.to_s == objeto
end

Para poder utilizarlo tal que
así:
case objeto
when “User” …
when “Thing” …
end

Aunque me parece un pelín peligrosillo, así que al final cambiaré la
forma de hacer las cosas :smiley:

Gracias a todos

David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

On Feb 15, 2007, at 1:51 PM, David A. wrote:

On 2/15/07, Xavier N. [email protected] wrote:

=== esta pensado para ser usado en las clausulas when de los case
statements (ni idea de como decir “statement” en castellano). Como
sabes Ruby lo usa alli transparentemente, por ello === no suele
invocarse directamente. Habria que redefenirlo o no en funcion de
eso.

Me parece estupenda esa característica de Ruby, el único problema es
cuando, por temas de namespaces, no puedo acceder a una clase desde un
módulo

A que te refieres? Sabes que puedes usar nombres fully-qualified para
acceder a cualquier namespace desde cualquier otro?

A = 1

module Foo
A = 2
end

module Bar
A = 3

 puts ::A
 puts Foo::A
 puts A

end

imprime

1
2
3

– fxn

Lo que no entiendo muy bien es porqué Object#=== es lo mismo que
Object#== ¿no sería mejor que Object#=== comprobara si el parámetro y
el objeto son de la misma clase? (supongo que hay una razón, pero no
la veo ahora mismo)

Porque en el caso de Object, tiene que proveer la implementacion mas
generica posible, pues tambien será empleada por todas las otras
subclases. Por ejemplo, dejaria de funcionar (apropiadamente) para
String.

Mientras que para Class es posible pensar en una implementacion mas
util (comparar objeto con clase, en lugar de clase con clase). Para
Range tambien hay buen uso.

On 2/15/07, Xavier N. [email protected] wrote:

A que te refieres? Sabes que puedes usar nombres fully-qualified para
acceder a cualquier namespace desde cualquier otro?

Sí, gracias Xavier, lo que no se es cuál es el nombre fully-qualified
de un modelo dentro de una aplicación Rails.

David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

On 2/15/07, Sebastian D. [email protected] wrote:

Porque en el caso de Object, tiene que proveer la implementacion mas
generica posible, pues tambien será empleada por todas las otras
subclases. Por ejemplo, dejaria de funcionar (apropiadamente) para
String.

Hola Sebastián,

No veo porqué es apropiado ese comportamiento para String, perdona si
es obvio pero hoy estoy de un espeso… :smiley:

¿No parece lógico esto?

“hola” === String
=> true

Quizá sólo me parezca lógico porque vengo de programar en PHP o Java,
porque si lo piensas bien esos dos objetos son de distinto tipo, es
uno de los inconvenientes (a nivel de expresividad del lenguaje) de
que las clases sean objetos ¿no es
así?–
David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

La forma como yo la entendi es que el operador == se traduce en “es
igual a”, mientras que === se traduce en simplemente “es” (aunque
para complicarlo un poco, el orden de los operadores es inverso, es
decir, a === b se lee como “b es a?”).

Es decir, el == es mas estricto, mientras que === es mas flexible (y
a veces ingenioso) en su interpretacion de igualdad. Pero esto
implica que como es mas flexible, no es simetrico o bidireccional.

Mira estos ejemplos:

variable == “prueba” # digamos que es cierto: “el contenido de
variable es igual a prueba”
variable == String # falso, “el contenido de variable NO es
igual a
la clase String”
variable.class == String # cierto, “la clase del contenido de
variable es igual a la clase String”

String === variable # cierto, “el contenido de variable es clase
String”
“prueba” === variable # cierto, “el contenido de variable es prueba”
variable === String # falso, “la clase String NO es prueba”

Y es importante entender ademas que el diseño de === no es
perfecto… yo ya me tope con un caso donde Ruby no respondio como me
lo esperaba: un metodo que recibia como parametro una clase, sobre la
cual debia hacer operaciones condicionales:

when variable_que_contiene_clase
case String
case Numeric
end

No funcionaba… porque variable_que_contiene_clase no es de clase
String, es de clase Class. Ese es un caso en que tanto a == b como b
== a son ciertos, pero fallan a===b y b===a.

Intenta con TuModulo::TuSubModulo::TuClase… o si no, con un ::
por delante, para asegurarte que lo busque en la raiz del espacio de
nombres (que deberia ser lo mismo, pero que a veces no lo es).

Si todos tus require’s aparecen fuera de tus modulos o clases,
entonces tus modulos o clases deberian estar definidos en ::

On Feb 15, 2007, at 4:46 PM, David A. wrote:

On 2/15/07, Xavier N. [email protected] wrote:

A que te refieres? Sabes que puedes usar nombres fully-qualified para
acceder a cualquier namespace desde cualquier otro?

Sí, gracias Xavier, lo que no se es cuál es el nombre fully-qualified
de un modelo dentro de una aplicación Rails.

Rails no mete modulos propios, si definiste

class User < AR::Base

end

como es usual en Rails, ahi la tienes silvestre en el top-level, como
Hash.

– fxn

On 2/15/07, Sebastian D. [email protected] wrote:

Intenta con TuModulo::TuSubModulo::TuClase… o si no, con un ::
por delante, para asegurarte que lo busque en la raiz del espacio de
nombres (que deberia ser lo mismo, pero que a veces no lo es).

Gracias a ti y a Xavier, ha funcionado perfectamente :slight_smile:

David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net

Javier,

¿Por que dices que en Ruby no se sobrecargan los métodos?

class MiString < String
def to_s
“mi string: #{super}”
end
end

irb(main):009:0> s = MiString.new(“hola”)
=> “hola”
irb(main):010:0> s.to_s
=> “mi string: hola”

¿o hay algo que me
perdí?
Salu2

On 2/15/07, javier ramirez [email protected] wrote:

teniendo disponible el método si lo hubiera de la clase padre mediante
http://lists.simplelogica.net/mailman/listinfo/ror-es


Edgar González González
E-mail: [email protected]
http://lacaraoscura.com
http://rubycorner.com
http://to2blogs.com

correcto !

Mi error estaba “leyendo” sobrecarga como override y no como overload

gracias

On 2/15/07, Sebastian D. [email protected] wrote:

por si he “malguiado” a alguien con mi deformación profesional, en
super)
http://lists.simplelogica.net/mailman/listinfo/ror-es


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Edgar González González
E-mail: [email protected]
http://lacaraoscura.com
http://rubycorner.com
http://to2blogs.com

Porque tecnicamente, no es sobrecarga… sobrecarga es cuando tienes
varios metodos con distintos tipos de parametros o retornos… En
ruby no hay tipos, asi que no puedes sobrecargar.