Clonable en clases derivadas

Supongo que tengo una clase Ay B que se deriva de A:

class A : ICloneable
{
    public object Clone() {...}
}

class B : A, ICloneable
{
    public object Clone() {...}
}

lo que da

'B.Clone()' hides inherited member 'A.Clone()'. Use the new keyword if hiding was intended.

advertencia.

(1) ¿Cuál es la forma sugerida? usando new o declarando A.Clone() as virtual y override in B?

(2) Si hay algunos miembros en A y correctamente clonado en A.Clone(), ¿existe una manera fácil de clonarlos en B.Clone() o tengo que clonarlos explícitamente en B.Clone() También?

preguntado el 31 de diciembre de 12 a las 16:12

1 Respuestas

Si tiene acceso a su fuente (que supongo que es el caso aquí), entonces absolutamente declarelo como virtual y anularlo. Si esconde la base Clone con new podría ser una mala idea. Si algún código no sabes qué que está trabajando con un B, entonces disparará el Mal método de clonación y no devuelve un clon adecuado.

Con respecto a la asignación de propiedades, tal vez considere implementar constructores de copia y cada nivel puede manejar su propia clonación:

    public class A : ICloneable
    {
        public int PropertyA { get; private set; }

        public A()
        {

        }

        protected A(A copy)
        {
            this.PropertyA = copy.PropertyA;
        }

        public virtual object Clone()
        {
            return new A(this);
        }
    }

    public class B : A, ICloneable
    {
        public int PropertyB { get; private set; }

        public B()
        {

        }

        protected B(B copy)
            : base(copy)
        {
            this.PropertyB = this.PropertyB;
        }

        public override object Clone()
        {
            return new B(this);
        }
    }

Cada constructor de copia llama al constructor de copia base pasándose a sí mismo por la cadena. Cada nivel de herencia copia las propiedades que le pertenecen directamente.

EDITAR: Si usas el new palabra clave para ocultar la implementación base, aquí hay un ejemplo de lo que podría suceder. Con una implementación de muestra (que a primera vista se ve bien)

public class A : ICloneable
{
    public int PropertyA { get; protected set; }

    public object Clone()
    {
        Console.WriteLine("Clone A called");
        A copy = new A();
        copy.PropertyA = this.PropertyA;
        return copy;
    }
}

public class B : A, ICloneable
{
    public int PropertyB { get; protected set; }

    public new object Clone()
    {
        Console.WriteLine("Clone B called");
        B copy = new B();
        copy.PropertyA = this.PropertyA;
        copy.PropertyB = this.PropertyB;
        return copy;
    }
}

Pero cuando lo usas:

B b = new B();
A a = b;
B bCopy = (B)a.Clone();
//"Clone A called" Throws InvalidCastException! We have an A!

Respondido el 31 de diciembre de 12 a las 16:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.