Usando métodos abstratos para forçar subclasses a definir valores para campos membros

5

Muitas vezes, em meus projetos, eu defino uma superclasse abstrata cujas subclasses irão variar principalmente em seus valores para os campos definidos na superclasse.

Por exemplo, em um jogo que estou desenvolvendo, há uma classe abstrata Missile com várias subclasses. Cada um deles define um valor diferente para variáveis membro, como MAX_SPEED , MASS , FLYING_FORCE , que são então usadas nos cálculos realizados na superclasse.

Eu uso métodos abstratos em Missile para forçar suas subclasses a definir essas variáveis. Por exemplo, eu simplesmente tenho um método abstrato defineMass() que força as subclasses a definir seu próprio valor de massa.

Um exemplo diferente seria minha Entity class (a superclasse de todas as classes de jogo) definindo um método loadImage() abstrato que força as subclasses a definir uma imagem para elas mesmas.

Esta é uma boa prática? É comum?

    
por Aviv Cohn 29.06.2014 / 01:57
fonte

4 respostas

4

Acho que a herança merece propósitos melhores:

  • Se a única coisa que varia entre subclasses e entre subclasses e sua superclasse são os valores de alguns membros, então você está abusando de herança ou usando errado. Você pode usar o padrão de construtor para criar mísseis com valores diferentes. Se o padrão do construtor for muito complexo para a tarefa, métodos de fábrica como buildMissileOfTypeA() e buildSuperMassiveMissile() servirão.
  • Você estaria colocando a herança em bom uso se os métodos abstratos estivessem relacionados a comportamentos que as subclasses implementariam de maneiras potencialmente diferentes, mas não apenas para definir um valor de um membro.
  • Além disso, você não está realmente forçando as subclasses a definir seu próprio valor, elas simplesmente podem implementar um método vazio que não altera o valor da massa e o compilador ficará satisfeito com isso.
por 29.06.2014 / 02:13
fonte
1

Se você quiser forçar uma subclasse a definir o campo do membro direito, você pode especificar um construtor com todos os parâmetros necessários na superclasse e, assim, forçar as subclasses a chamar o construtor (desde que seu idioma escolha forçar a chamada super construtores).

    
por 29.06.2014 / 20:29
fonte
1

Eu colocaria esses campos no construtor, por exemplo

public abstract class Missile
{
    int MAX_SPEED, MASS, FLYING_FORCE

    Missile(int maxSpeed, int mass, int flyingForce)
    {
        MAX_SPEED = maxSpeed;
        MASS = MASS;
        FLYING_FORCE = flyingForce;
    }
}

Em seguida, crie as classes filhas da seguinte forma, por exemplo,

public class Rocket extends Missile
{
     Rocket()
     {
         super(100, 20, 50);
     }
}

Portanto, os campos devem ser declarados sempre que a classe Missile for chamada, mas pode ser muito bem organizada em suas classes filho.

    
por 26.11.2016 / 18:27
fonte
0

É um padrão que vi e usei com frequência, e vejo isso como uma forma do padrão de método de modelo .

Considere uma classe BasePlugin , por exemplo, que define as propriedades abstratas Name e SupportedTypes . Essas propriedades são usadas como parte das implementações compartilhadas da classe base - usando Name para log, talvez, ou usando SupportedTypes para validação. Isso pode ser um acréscimo à lógica substituída de ExecutePlugin ou qualquer outra coisa.

Uma alteração que eu faria em seu design é definir um método getMass (ou, se em linguagem C # ou semelhante, uma propriedade com um getter) em vez de seu defineMass . O nome de getMass implica que seu uso é como um getter, usado em qualquer lugar no código da classe base onde o valor é necessário. defineMass implica que ele será chamado no construtor, e ele próprio armazenará um valor em um campo na classe base. Isso parece desnecessário e faz com que defineMass tenha efeitos colaterais (possivelmente afetando o código multithread) ou, alternativamente, apenas não seja um nome muito descritivo, supondo que você tenha pretendido que seja um getter.

Em vez de "forçar a classe derivada a definir os valores", que é apenas uma forma indireta de dizer "Preciso dos valores da classe derivada", simplesmente peça a classe derivada para o valor e deixe faça o que for preciso para dar a você.

    
por 29.06.2014 / 19:46
fonte