casi todos los lenguajes de programación orientados a objetos proporcionan alguna forma de copiar objetos. Como la mayoría de los lenguajes no proporcionan la mayoría de los objetos para los programas, un programador debe definir cómo se debe copiar un objeto, al igual que debe definir si dos objetos son idénticos o incluso comparables en primer lugar. Muchos idiomas proporcionan algún comportamiento predeterminado.
Cómo se resuelve la copia varía de un idioma a otro, y qué concepto de objeto tiene.
Lazy copyEdit
una copia perezosa es una implementación de una copia profunda., Al copiar inicialmente un objeto, se utiliza una copia superficial (rápida). Un contador también se utiliza para rastrear cuántos objetos comparten los datos. Cuando el programa quiere modificar un objeto, puede determinar si los datos se comparten (examinando el contador) y puede hacer una copia profunda si es necesario.
Lazy copy se ve hacia el exterior como una copia profunda, pero aprovecha la velocidad de una copia superficial siempre que sea posible. La desventaja son los costos básicos bastante altos pero constantes debido al contador. Además, en ciertas situaciones, las referencias circulares pueden causar problemas.
Lazy copy está relacionado con copy-on-write.,
en JavaEdit
a continuación se presentan ejemplos de uno de los lenguajes orientados a objetos más utilizados, Java, que debería cubrir casi todas las formas en que un lenguaje orientado a objetos puede tratar este problema.
a diferencia de C++, los objetos en Java siempre se accede indirectamente a través de referencias. Los objetos nunca se crean implícitamente, sino que siempre se pasan o asignan por una variable de referencia. (Los métodos en Java son siempre pasar por valor, sin embargo, es el valor de la variable de referencia que se está pasando.,) La máquina virtual Java administra la recolección de basura para que los objetos se limpien después de que ya no sean accesibles. No hay una forma automática de copiar cualquier objeto dado en Java.
el copiado es usualmente realizado por un método clone () de una clase. Este método generalmente, a su vez, llama al método clone() de su clase padre para obtener una copia, y luego realiza cualquier procedimiento de copia personalizado., Eventualmente esto llega al método clone () de Object
(la clase más alta), que crea una nueva instancia de la misma clase que el objeto y copia todos los campos a la nueva instancia (una «copia superficial»). Si se utiliza este método, la clase debe implementar la interfaz de marcador Cloneable
, o de lo contrario lanzará una CloneNotSupportedException. Después de obtener una copia de la clase padre, el propio método clone() de una clase puede proporcionar una capacidad de clonación personalizada, como la copia profunda (i. e., duplicar algunas de las estructuras a las que hace referencia el objeto) o dar a la nueva instancia un nuevo ID único.
el tipo de retorno de clone() es Object
, pero los implementadores de un método de clonación podrían escribir el tipo del objeto que se clona en su lugar debido al soporte de Java para tipos de retorno covariantes. Una ventaja de usar clone() es que dado que es un método overridable, podemos llamar a clone() en cualquier objeto, y usará el método clone () de su clase, sin que el código de llamada necesite saber qué clase es (lo que sería necesario con un constructor de copia).,
una desventaja es que a menudo no se puede acceder al método clone () en un tipo abstracto. La mayoría de las interfaces y clases abstractas en Java no especifican un método clone() público. Por lo tanto, a menudo la única manera de usar el método clone() es si se conoce la clase de un objeto, lo que es contrario al principio de abstracción de usar el tipo más genérico posible. Por ejemplo, si uno tiene una referencia List en Java, no se puede invocar clone() en esa referencia porque List no especifica ningún método clone() público., Las implementaciones de List como ArrayList y LinkedList generalmente tienen métodos clone (), pero es una abstracción inconveniente y mala llevar el tipo de clase de un objeto.
otra forma de copiar objetos en Java es serializarlos a través de la interfaz Serializable
. Esto se usa típicamente para propósitos de persistencia y Protocolo de alambre, pero crea copias de objetos y, a diferencia del clon, una copia profunda que maneja gráficamente gráficos cíclicos de objetos está fácilmente disponible con el mínimo esfuerzo de un programador.,
ambos métodos tienen un problema notable: el constructor no se usa para objetos copiados con clonación o serialización. Esto puede conducir a errores con datos inicializados incorrectamente, evita el uso de campos de miembros final
y hace que el mantenimiento sea un desafío. Algunas utilidades intentan superar estos problemas mediante el uso de reflexión para copiar objetos en profundidad, como la biblioteca de clonación profunda.,
en EiffelEdit
los objetos de tiempo de ejecución en Eiffel son accesibles indirectamente a través de referencias o como objetos expandidos cuyos campos están incrustados dentro de los objetos que los usan. Es decir, los campos de un objeto se almacenan externa o internamente.
La Clase Eiffel ANY
contiene funciones para copiar y clonar objetos de forma superficial y profunda. Todas las clases Eiffel heredan de ANY
, por lo que estas características están disponibles dentro de todas las clases y son aplicables tanto a los objetos de referencia como a los expandidos.,
la característica copy
produce una copia superficial, campo por campo, de un objeto a otro. En este caso no se crea ningún objeto nuevo. Si y
copiar x
, entonces el mismo los objetos referenciados por y
antes de la aplicación de copy
, también se hace referencia x
después de copy
función completa.,
para efectuar la creación de un nuevo objeto que es un duplicado superficial de y
, se utiliza la característica twin
. En este caso, se crea un nuevo objeto con sus campos idénticos a los del origen.
característica twin
se basa en la función de copy
, que puede ser redefinido en los descendientes de ANY
, si es necesario. El resultado de twin
es del tipo anclado like Current
.,
la copia profunda y la creación de gemelos profundos se pueden hacer utilizando las características deep_copy
y deep_twin
, nuevamente heredadas de la clase ANY
. Estas características tienen el potencial de crear muchos objetos nuevos, porque duplican todos los objetos en una estructura de objetos completa. Debido a que se crean nuevos objetos duplicados en lugar de simplemente copiar referencias a objetos existentes, las operaciones profundas se convertirán en una fuente de problemas de rendimiento más fácilmente que las operaciones superficiales.,
en otros idiomaseditar
en C#, En lugar de usar la interfaz ICloneable
, se puede usar un método de extensión genérico para crear una copia profunda usando reflexión. Esto tiene dos ventajas: en primer lugar, proporciona la flexibilidad de copiar cada objeto sin tener que especificar cada propiedad y variable a copiar manualmente. En segundo lugar, debido a que el tipo es genérico, El compilador garantiza que el objeto de destino y el objeto de origen tengan el mismo tipo.,
en Objective-C, los métodos copy
y mutableCopy
son heredados por todos los objetos y están destinados a realizar copias; este último es para crear un tipo mutable del objeto original. Estos métodos a su vez llaman a los métodos copyWithZone
y mutableCopyWithZone
, respectivamente, para realizar la copia. Un objeto debe implementar el método copyWithZone
correspondiente para ser copiable.
en OCaml, la función de biblioteca Oo.copy realiza una copia superficial de un objeto.,
en Ruby, todos los objetos heredan dos métodos para realizar copias superficiales, clone y dup. Los dos métodos difieren en que clone
copia el estado tainted de un objeto, el estado frozen y cualquier método singleton que pueda tener, mientras que dup
copia solo su estado tainted. Las copias profundas se pueden lograr descargando y cargando el flujo de bytes de un objeto o la serialización YAML. Alternativamente, puede usar la gema deep_dive para hacer una copia profunda controlada de sus gráficos de objetos.,
en Perl, las estructuras anidadas se almacenan mediante el uso de referencias, por lo que un desarrollador puede recorrer toda la estructura y volver a referenciar los datos o usar la función dclone()
del módulo almacenable.
en VBA, una asignación de variables de tipo Object
es una copia superficial, una asignación para todos los demás tipos (tipos numéricos, cadena, tipos definidos por el usuario, matrices) es una copia profunda. Por lo tanto, la palabra clave Set
para una asignación señala una copia superficial y la palabra clave (opcional) Let
señala una copia profunda., No hay un método incorporado para copias profundas de objetos en VBA.
Deja una respuesta