2008-10-08 9 views
5

Tengo un objeto que estoy pasando en una llamada a método. Digamos que estoy usando un lenguaje que solo le permite pasar objetos por referencia, como Java o PHP. Si el método realiza cambios en el objeto, afectará a la persona que llama. No quiero que esto suceda. Entonces parece que necesito hacer una copia del objeto.Transferencia de objeto a método: ¿quién hace la copia?

Mi pregunta es: ¿de quién es la responsabilidad de clonar el objeto? La persona que llama, antes de llamar al método? ¿O el llamado, antes de que cambie el objeto?

EDITAR: Solo para aclarar, quiero que esto sea parte del contrato de este método, que nunca modifica el objeto original. Por lo tanto, parece que debería depender el método para hacer la copia. Pero entonces la persona que llama no tiene protección de un método que no hace esto correctamente. Supongo que eso es aceptable, la única alternativa parece ser tener esto incorporado en el lenguaje.

+0

No entiendo esto. Usted tiene un método que realiza cambios en un objeto, pero el contrato implícito del método es que no lo hace. ¿Podrías aclarar esto más? –

+0

Se supone que el método no afecta al objeto de la persona que llama, pero puede cambiar su propia copia del objeto. –

Respuesta

0

Depende, ¿hay algún motivo por el que se pueda llamar al método en el futuro en el que desee que la persona que llama vea el cambio? Si es así, la persona que llama debe hacer la copia. De lo contrario, el destinatario debería hacerlo. Yo diría que el segundo caso es probablemente más común.

5

Generalmente, el llamante debe hacer la copia si le preocupan los cambios. Si a la persona que llama no le importa, el método debe hacer la copia si necesita hacer algo que sabe que no debe persistir.

0

Si hace que la persona que llama clone el objeto, le da la flexibilidad de no usar una copia (al no clonarlo primero), y también significa que no tiene que devolver un nuevo objeto, puede simplemente operar en la referencia pasó.

0

Mi primera reacción sería que es la responsabilidad del que llama, pero creo que realmente depende.

Depende del contrato definido entre los dos métodos. El método que realiza los cambios debe identificar explícitamente ese hecho y dejar que quien llama tome la decisión. O BIEN, el método que realiza los cambios debe identificar explícitamente que NO realizará ningún cambio en el objeto pasado y que entonces sería responsable de realizar la copia.

1

La persona que llama. Porque, a veces, desea realizar cambios en los objetos en sí mismos y otras veces en una copia.

Aunque, considero que es una mala práctica para callee modificar los objetos pasados ​​(al menos en los lenguajes orientados a objetos). Esto puede causar muchos efectos secundarios no deseados.

(después) EDIT: En ese caso, es responsabilidad del destinatario de la llamada para hacer cumplir el contrato, por lo que hay dos opciones:

  • El destinatario de la llamada, simplemente no modifica el objeto
  • o las copias Callee las los objetos y trabaja con la copia después
+0

Esto suena correcto, que es el contrato del que llama, y ​​por lo tanto es responsabilidad. Pero entonces, ¿no le damos demasiado poder y no lo encapsulamos? Ahora puede hacer daño fuera de sí mismo. –

+0

Si cumple con el contrato al garantizar que no se modifiquen los objetos pasados, entonces no hay efectos secundarios y no se produce ningún daño. –

1

Así que quieres hacer algo como

MiObjeto m = new MiObjeto(); MyObject n = MyObjectProcessor.process (m) ;?

Me parece más simple hacer algo como MyObject n = MyObjectProcessor.alter (m.clon());

donde está claro quién está haciendo qué a quién. Podría argumentar que la función de clase del procesador debería estar libre de efectos secundarios, es decir, debería devolver un nuevo objeto cada vez que cambie de estado, pero (AFAIK) no se sigue tan consistentemente en OO en comparación con la programación funcional.

Algo similar a lo anterior probablemente sea inofensivo, siempre que esté claramente identificado y documentado.

1

Podríamos mirar ruby ​​para una guía. Ellos usan a! símbolo para indicar que un objeto se modifica in situ. Entonces, salario.add (10000) devuelve un nuevo objeto pero salario.add! (10000) devuelve el objeto original pero modificado. Puede usar la misma idea en Java o PHP utilizando una convención de nomenclatura local.

0

Yo diría que el llamado: simplifica las llamadas y la persona que llama no tendrá que preocuparse por la integridad de los objetos especificados. Es responsabilidad del destinatario de la llamada preservar la integridad.

0

Supongo que tendrías algo así como la declaración const. Esto sería implementado por el compilador y sería más eficiente que crear copias de sus objetos.

0

Creo que la persona que llama debe hacer el clon, solo para hacer que el nombramiento sea más fácil. Puede nombrar su método Foo() en lugar de CloneBarAndFooClone().

Compare:

void RemoveZeroDollarPayments(Order order) 

vs

Order CloneOrderAndRemoveZeroDollarPaymentsFromClone(Order order) 
0

Si no cambia el objeto es parte del contrato método, la única posibilidad es tener la copia que se haga dentro del método. De lo contrario, le estás mintiendo a tu cliente.

El hecho de que realmente necesite modificar un objeto exactamente como el que le dieron es solo un detalle de implementación que no debe ser una carga para la persona que llama. De hecho, ni siquiera necesita tener visibilidad de eso.

Cuestiones relacionadas