Estou acompanhando essa pergunta , mas estou mudando meu foco do código para um princípio.
Pelo meu entendimento do princípio de substituição de Liskov (LSP), quaisquer que sejam os métodos da minha classe base, eles devem ser implementados na minha subclasse e, de acordo com esta página, se você substituir um método na classe base e ele não fizer nada ou lançar um exceção, você está violando o princípio.
Agora, meu problema pode ser resumido assim: eu tenho um resumo Weapon
class
e duas classes Sword
e Reloadable
. Se Reloadable
contiver um específico method
, chamado Reload()
, eu teria que fazer o downcast para acessá-lo method
e, idealmente, você desejaria evitar isso.
Eu então pensei em usar o Strategy Pattern
. Dessa forma, cada arma estava ciente das ações que é capaz de executar; portanto, por exemplo, uma Reloadable
arma pode obviamente ser recarregada, mas Sword
não pode e nem sequer sabe de uma Reload class/method
. Como afirmei na postagem Stack Overflow, não preciso fazer downcast e posso manter uma List<Weapon>
coleção.
Em outro fórum , a primeira resposta sugerida para permitir Sword
estar ciente Reload
, simplesmente não faça nada. Essa mesma resposta foi dada na página Estouro de pilha à qual vinculei acima.
Eu não entendo completamente o porquê. Por que violar o princípio e permitir que a Sword esteja ciente Reload
, e deixe em branco? Como eu disse no meu post Stack Overflow, o SP praticamente resolveu meus problemas.
Por que não é uma solução viável?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
Interface e Implementação de Ataques:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()
branco ou se standardActions
não contém uma ação de recarga é apenas um mecanismo diferente. Não há diferença fundamental. Você pode fazer as duas coisas. => Sua solução é viável (qual foi sua pergunta) .; O Sword não precisa saber sobre recarregar se o Weapon contém uma implementação padrão em branco.
class Weapon { bool supportsReload(); void reload(); }
. Os clientes testariam se suportado antes de recarregar.reload
é definido contratualmente para lançar iff!supportsReload()
. Isso adere ao LSP se as classes dirigidas aderem ao protocolo que acabei de descrever.