Estou projetando meu próprio programa OOP para simular vampiros, lobos, humanos e caminhões e estou tentando implementar meu próprio entendimento limitado de interfaces.
( Ainda estou abstraindo aqui e ainda não tenho implementação de código, então é uma questão de design de OOP ... eu acho!)
Estou certo ao procurar 'comportamento comum' entre essas classes e implementá-las como interfaces ?
Por exemplo, vampiros e lobos mordem ... então eu deveria ter uma interface de mordida?
public class Vampire : Villain, IBite, IMove, IAttack
Da mesma forma para caminhões ...
public class Truck : Vehicle, IMove
E para os humanos ...
public class Man : Human, IMove, IDead
O meu pensamento está aqui? (Agradeço sua ajuda)
object-oriented
interfaces
user3396486
fonte
fonte
IEnumerable
,IEquatable
, etc.Respostas:
Em geral, você deseja ter interfaces para características comuns da sua classe.
Eu concordo parcialmente com @Robert Harvey nos comentários, que disseram que geralmente as interfaces representam características mais abstratas das classes. No entanto, acho que a partir de exemplos mais concretos é uma boa maneira de começar a pensar abstrato.
Embora seu exemplo seja tecnicamente correto (ou seja, sim, vampiros e lobos mordem, para que você possa ter uma interface para isso), há uma questão de relevância. Cada objeto tem milhares de características (por exemplo, os animais podem ter pêlos, podem nadar, podem escalar árvores etc.). Você fará uma interface para todos eles? Muito menos provável.
Você geralmente deseja que interfaces para coisas que fazem sentido sejam agrupadas em um aplicativo como um todo. Por exemplo, se você estiver criando um jogo, poderá ter uma matriz de objetos IMove e atualizar sua posição. Se você não quiser fazer isso, ter a interface IMove é bastante inútil.
O ponto é, não exagere na engenharia. Você precisa pensar em como vai usar essa interface, e 2 classes com um método em comum não são um motivo suficientemente bom para criar uma interface.
fonte
IBite
não é particularmente útil, mas você pode quererIAttack
trabalhar com todas as coisas que fazem ataques, ou umIUpdate
para executar as atualizações de tudo, ou umIPhysicsEnabled
para aplicar a física a eles etc.Parece que você está criando várias interfaces de método único . Isso é bom, mas lembre-se de que as interfaces não pertencem às classes que os implementam. Eles pertencem aos clientes que os utilizam. Os clientes decidem se algo precisa ser algo que possa se mover e atacar.
Se eu tiver uma
Combat
classe com umfight()
método, esse método provavelmente precisará chamar ambosmove()
eattack()
no mesmo objeto. Isso sugere fortemente a necessidade de umaICombatant
interface quefight()
possa chamarmove()
eattack()
através. É mais limpo do quefight()
pegar umIAttack
objeto e lançá-loIMove
para ver se ele também pode se mover.Isso não significa que você também não pode ter
IMove
IAttack
interfaces. Eu só espero que você não os esteja fazendo sem que algum cliente precise deles. Por outro lado, se nenhum cliente precisar fazer com que um objeto se mova e ataque,ICombatant
não será necessário.Essa maneira simples de ver as interfaces geralmente se perde porque as pessoas gostam de seguir exemplos. As primeiras interfaces às quais estamos expostos estão nas bibliotecas. Infelizmente, as bibliotecas não têm idéia do que são seus clientes. Assim, eles podem apenas adivinhar as necessidades de seus clientes. Não é o melhor exemplo a seguir.
fonte
Considere se será comum ter coleções de objetos com diferentes combinações de habilidades e se o código pode querer executar uma ação sobre esses itens, dentro de uma coleção, que o suportam . Nesse caso, e se houver um "comportamento padrão" sensato para objetos que não têm suporte útil para alguma ação, pode ser útil ter interfaces implementadas por uma ampla gama de classes, não apenas aquelas que podem se comportar de maneira útil.
Por exemplo, suponha que apenas alguns tipos de criatura possam ter Woozles, e alguém deseja que essas criaturas tenham uma
NumerOfWoozles
propriedade. Se essa propriedade estivesse em uma interface implementada apenas por criaturas que podem ter Woozles, o código que desejasse encontrar o número total de Woozles mantidos por uma coleção de criaturas de tipos mistos teria que dizer algo como:Se, no entanto, o WoozleCount fosse um membro do Creature / ICreature, mesmo que poucos subtipos substituíssem a implementação padrão do WoozleCount do Creature que sempre retorna zero, o código poderia ser simplificado para:
Embora algumas pessoas possam se irritar com a idéia de todas as Criaturas implementarem uma propriedade WoozleCount que seja realmente útil apenas para alguns subtipos, a propriedade seria significativa para todos os tipos, independentemente de ser útil ou não com itens conhecidos por esses tipos, e eu consideraria a interface "pia da cozinha" menos odor de código do que o operador trycast.
fonte