Ищем реализацию Clone() с производным типом возврата
Я уверен, что это должен быть дубликат, но я не могу найти ответ:
Если у меня есть два класса:
public class BASE
{
public BASE() {};
public abstract BASE clone();
}
public class CHILD : BASE
{
public CHILD() : base() {}
public override BASE clone()
{
return new CHILD();
}
}
Я должен делать явное преобразование каждый раз, когда хочу клонировать объект типа CHILD, например:
var a = new CHILD();
CHILD b = a.clone() as CHILD;
Есть ли способ избежать этого преобразования? Я хотел бы иметь возможность написать:
var original = new CHILD();
BASE copy1 = original.clone();
CHILD copy2 = original.clone();
Возможно ли это в C#?
3 ответа
Есть ли способ избежать этого преобразования?
Не перегружая Clone
- вы не можете перегрузить метод, просто изменив его тип возвращаемого значения. Вместо этого используйте другой метод:
public class CHILD : BASE
{
public CHILD() : base() {}
public BASE clone() { return this.cloneChild();}
public CHILD cloneChild()
{
return new CHILD();
}
}
Если вы хотите применить это поведение ко всем унаследованным классам, вы можете сделать BASE
общий:
public abstract class BASE<T> where T:BASE<T>
{
public BASE() {}
public abstract T clone();
}
public class CHILD : BASE<CHILD>
{
public CHILD() : base() {}
public override CHILD clone()
{
return new CHILD();
}
}
Если тебе надо CHILD
тип вместо BASE
введите в clone
, тогда вам нужно сделать скрытие метода вместо переопределения метода. Вы должны удалить override
ключевое слово и использование new
вместо:
public class BASE
{
public BASE() {};
public abstract BASE clone();
}
public class CHILD : BASE
{
public CHILD() : base() {}
public new CHILD clone()
{
return new CHILD();
}
}
C# не поддерживает ковариацию возвращаемого типа. Вы можете попробовать этот обходной путь (используя дженерики):
public class Base<T> {
public abstract T Clone()
}
public class Child : Base<Child> {
public override Child Clone() {
return ...;
}
}