2009-08-06 19 views
26

Tengo una clase de modelo de base de datos que es NSObject. Tengo un conjunto de estos objetos en un NSMutableArray. Yo uso indexOfObject: para encontrar una coincidencia. El problema es que la dirección de memoria del objeto modelo cambia. De modo que anulo el método hash para devolver la identificación de la fila del modelo. Sin embargo, esto no lo soluciona. También tengo que anular el método isEqual: para comparar el valor del método hash.¿Qué es la función predeterminada de NSObject isEqual: y hash?

¿Qué utiliza el método isEqual: para determinar la igualdad de forma predeterminada?

Supongo que usa la dirección de memoria. Después de leer la documentación isEqual: pensé que usaba el valor del método hash. Obviamente, ese no es el caso, ya que mi intento de anular ese valor no resolvió mi problema inicial.

+0

Aquí hay algunas respuestas especulativas. ¿Alguien puede proporcionar la documentación actual de que el valor predeterminado es que Equals usa la dirección? No estoy sugiriendo que no lo haga, solo me gustaría escucharlo de la boca del caballo. – DougW

+0

@DougW Compartí tus sentimientos sobre esto, así que rastreé una referencia oficial y la edité en la respuesta aceptada. –

+0

Está leyendo los documentos para el protocolo NSObject, no la clase NSObject. El protocolo define qué deben hacer los métodos, la clase no puede definir lo que realmente hace. Siempre es más seguro anular equals y hash para trabajar cómo quieres que funcionen. –

Respuesta

26

Como ha adivinado correctamente, el comportamiento predeterminado de NSObjectisEqual: es comparar la dirección de memoria del objeto. Curiosamente, esto no está actualmente documentada en el NSObject Class Reference, pero se documenta en la documentación Introspection, que establece:

La implementación predeterminada de NSObjectisEqual: simplemente comprueba por la igualdad puntero.

Por supuesto, ya que son sin duda conscientes, subclases de NSObject puede anular isEqual: a comportarse de manera diferente. Por ejemplo, el método NSStringisEqual:, al pasar otro NSString, primero verificará la dirección y luego buscará una correspondencia literal exacta entre las cadenas.

+0

Una referencia para esto sería bueno. –

+1

... así que agregué uno. Curiosamente, la referencia de clase 'NSObject' ni siquiera tiene una entrada para' isEqual: ', y mucho menos describe su comportamiento en cualquier lugar, lo que parece una omisión flagrante. Sin embargo, pude rastrear una referencia oficial en una página oscura en la sección 'conceptual' de los documentos. –

+0

La documentación de Apple está plagada de casos en los que los métodos de protocolo no están documentados en la documentación de la clase. (Sin mencionar los métodos de superclase.) A menudo hay que mirar debajo de muchas rocas para encontrar documentación para un método dado. –

4

Supongo que NSObjectisEquals usa el operador ==, y hash usa la dirección de memoria.

método isEquals nunca debe usar hash como una prueba absoluta para la igualdad. Se garantiza que tenga dos objetos que tengan hashCode similar, si busca objetos suficientes (solo cree más de 2^32 objetos diferentes, y al menos dos de ellos tendrán el mismo hash).

En otras palabras, hash requiere la siguiente especificación: Si dos objetos son iguales, entonces su hash debe ser igual; sin embargo, si los valores de dos objetos 'hash son iguales, no son necesariamente iguales.

Como sugerencia, siempre debe anular isEquals y hashCode juntos.

+21

"Asumiría" es una desafortunada cosa comenzar una respuesta con ... –

8

La respuesta sobre la implementación predeterminada de isEqual: es exhaustiva. Así que solo agrego mi nota sobre la implementación predeterminada de hash. Aquí está:

-(unsigned)hash {return (unsigned)self;} 

es decir que es sólo el mismo valor del puntero que se utiliza en isEqual:.Así es como se puede comprobar esto:

NSObject *obj = [[NSObject alloc] init]; 
NSLog(@"obj: %@",obj); 
NSLog(@"hash: %x",obj.hash); 

El resultado será algo como esto:

obj: <NSObject: 0x16d44010> 
hash: 16d44010 

Saludos.

BTW en iOS 8 hash se convirtió en una propiedad, no en un método, pero está ahí.

Cuestiones relacionadas