2012-08-14 14 views
9

Tengo una clase Pointer con un solo atributo :contents, que apunta a un objeto de la clase MyObject.¿Qué método para definir en una clase de Ruby para proporcionar dup/clone para sus instancias?

class MyObject 
    def hello; "hello" end 
end 

class Pointer 
    attr_reader :contents 
    def initialize(cont); @contents = cont end 
    # perhaps define some more state 
end 

Quiero que mi Pointer para ser capaz de hacer copias de sí mismo. Sé que el método #dup se define de forma predeterminada, mientras que se espera que el método #clone se sobrescriba para poder hacer copias en profundidad. Pero aquí, las copias no tienen que ser demasiado profundas. Entonces, el primer dilema que tengo es, ¿debo anular el método #dup, porque realmente no quiero copiar el estado adicional de mi Pointer, simplemente haga uno nuevo apuntando a la misma instancia MyObject? ¿O debería abstenerme de omitir #dup, porque no se "debería" y anular #clone con un método de hacer copias superficiales?

Me gustaría recibir comentarios sobre lo anterior, pero digamos que elegiré anular #dup. Podría hacer precisamente esto:

class Pointer 
    def dup; self.class.new(contents) end 
end 

Pero en línea, leí algo así como "el DUP método llamará al inicializar copiar método". Además, this guy escribe sobre #initialize_clone, #initialize_dup y #initialize_copy en Ruby. Eso me deja pensando, ¿es la mejor práctica tal vez así?

class Pointer 
    def initialize_copy 
    # do I don't know what 
    end 
end 

¿Te gusta esto?

class Pointer 
    def initialize_dup 
    # do I don't know what 
    end 
end 

O debería olvidarse de diatribas en línea escritas para confundir a los principiantes e ir a por anulando #dup sin preocupaciones?

Además, entiendo que solo puedo llamar #dup sin definir ninguna costumbre #dup, pero lo que si quiero definir #dup con un comportamiento diferente?

Además, la misma pregunta se aplica a #clone - ¿Debería tratar de definir #initialize_clone o simplemente #clone?

+0

¿Puedo preguntar por qué usted está haciendo una clase de puntero en absoluto ? Las variables de Ruby ya son referencias/punteros. –

+0

Algunas veces quiere implementar su propia estructura de datos o quiere que el puntero haga trucos. El objeto de la pregunta no es si la clase es un puntero u otra cosa, pero si debes saberlo, estoy interesado en las estructuras Zz de Ted Nelson, y Ted define lo que él llama "cursores", así que decidí llamarlos "puntos" "como en Emacs". Ya sabes, tienes que implementar la clase de puntero cuando la especificación de la estructura de datos lo requiera. –

Respuesta

16

Desde mi experiencia, la sobrecarga #initialize_copy funciona bien (nunca escuché sobre initialize_dup y initialize_clone).

El initialize_copy original (que inicializa cada variable de instancia con los valores del objeto original) está disponible a través estupendo, por lo que suelen hacer:

class MyClass 
    def initialize_copy(orig) 
    super 
    # Do custom initialization for self 
    end 
end 
+0

¿Cómo se compara con la redefinición de #dup? ¿Alguna vez o.k. para redefinir #dup? –

+3

La gran diferencia es que, cuando redefine #dup, 'self' es el objeto original.Por lo tanto, no tiene acceso al estado interno del nuevo objeto. Es al revés en #initialize_copy –

+2

Una diferencia más: aprendí por las malas que, en la implementación de Matz 'Ruby, algunas funciones de C llaman p. rb_obj_dup directamente en lugar de usar el despacho de método normal. #dup podría ser uno de ellos. Lo que significa que algunas cosas de la biblioteca estándar * no * llamarían a tu versión de #dup mientras * llamarían * #initialize_copy –

Cuestiones relacionadas