Execução do clone () método em base de classe
-
22-08-2019 - |
Pergunta
Aqui está uma implementação Clone()
para minha classe:
MyClass^ Clone(){
return gcnew MyClass(this->member1, this->member2);
}
Agora eu tenho cerca de 10 classes derivadas de MyClass
. A implementação é o mesmo em cada caso. Devido ao fato de que eu preciso gcnew
chamada com o nome real da classe em cada caso, eu sou obrigado a criar 10 implementações quase idênticas de Clone()
.
Existe uma maneira de escrever um método Clone()
único na classe base que servirá todas as 10 classes derivadas?
Editar: Existe uma maneira de chamar o construtor de uma classe através de um de seus objetos? De uma forma que irá chamar o construtor real classe derivada. Algo como:
MyClass ^obj2 = obj1->Class->Construct(arg1, arg2);
Estou fazendo isso em C ++ / CLI, mas respostas de outros idiomas são bem-vindos.
Solução
Na planície antiga C ++, você pode fazer isso com o polimorfismo em tempo de compilação (o padrão modelo curiosamente recorrente). Assumindo as suas classes derivadas são copiável, você pode apenas escrever:
class Base
{
public:
virtual Base* Clone() const = 0;
//etc.
};
template <typename Derived>
class BaseHelper: public Base
{
//other base code here
//This is a covariant return type, allowed in standard C++
Derived * Clone() const
{
return new Derived(static_cast<Derived *>(*this));
}
};
Em seguida, usá-lo como:
class MyClass: public BaseHelper<MyClass>
{
//MyClass automatically gets a Clone method with the right signature
};
Note que você não pode derivar de uma classe novamente e tê-lo funcionar perfeitamente -. Você tem que "design no" a opção para derivar novamente por templates as classes intermediárias, ou iniciar Clone
-escrevendo re novamente
Outras dicas
Não em C ++ que eu estou ciente. Como você disse, você precisa criar um objeto de uma classe diferente em cada implementação de Clone ().
Hm, acho que você pode usar o padrão de fábrica aqui. Ou seja:.
MyClass Clone(){
return MyClassFactory.createInstance(this.getClass(), this.member1, this.member2, ...);
}
Na fábrica, você teria que criar instância da subclasse com base no tipo de classe passou. Então, provavelmente, ele tem as mesmas desvantagens como a sua abordagem.
Gostaria de sugerir o uso de construtores de cópia em vez (como as classes derivadas pode chamar construtor de cópia da implementação base também) - também acessível, pois será um território familiar para programadores C ++.
Você pode ser capaz de criar um único método Clone que usa reflexão para chamar o construtor de cópia de si mesmo neste caso.
Possivelmente importante notar também que Jeffrey Richter diz no livro Framework Design Guidelines, "A interface ICloneable é um exemplo de uma abstração muito simples, com um contrato que nunca foi documentado explicitamente. Alguns tipos de implementar o método Clone
deste interface para que ele executa uma cópia superficial do objeto, enquanto que algumas implementações executar uma cópia profunda. Porque o que método Clone
desta interface deve fazer nunca mais foi totalmente documentado, ao usar um objeto com um tipo que implementa ICloneable
, você nunca sabe o que você vai conseguir. Isso faz com que a interface inútil "(grifo meu)