Клонируемый в производных классах
Предположим, у меня есть класс A
, а также B
который вытекает из A
:
class A : ICloneable
{
public object Clone() {...}
}
class B : A, ICloneable
{
public object Clone() {...}
}
который дает
'B.Clone()' hides inherited member 'A.Clone()'. Use the new keyword if hiding was intended.
предупреждение.
(1) Каков предлагаемый способ? с помощью new
или объявив A.Clone()
как virtual
а также override
в B
?
(2) Если в A
и правильно клонируется в A.Clone()
Есть ли простой способ клонировать их в B.Clone()
или я должен явно клонировать их в B.Clone()
также?
1 ответ
Если у вас есть доступ к вашему источнику (который, как я предполагаю, имеет место здесь), тогда абсолютно объявите его как virtual
и переопределить это. Если скрыть базу Clone
с new
может быть плохая идея Если какой-либо код не знает, что он работает с B
тогда он запустит неправильный метод клонирования и не вернет правильный клон.
Что касается присвоения свойств, возможно, рассмотрите возможность реализации конструкторов копирования, и каждый уровень может обрабатывать свое собственное клонирование:
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);
}
}
Каждый конструктор копирования вызывает базовый конструктор копирования, передавая себя по цепочке. Каждый уровень наследования копирует принадлежащие ему свойства напрямую.
РЕДАКТИРОВАТЬ: Если вы используете new
Ключевое слово, чтобы скрыть базовую реализацию, вот пример того, что может произойти. С примером реализации (который на первый взгляд выглядит нормально)
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;
}
}
Но когда вы используете это:
B b = new B();
A a = b;
B bCopy = (B)a.Clone();
//"Clone A called" Throws InvalidCastException! We have an A!