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:
int total = 0;
foreach (object it in creatures)
{
IWoozleCountable w = trycast(it, IWoozleCountable);
if (w != null) total += w.WoozleCount;
}
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:
int total = 0;
foreach (ICreature it in creatures)
total += it.WoozleCount;
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.
IEnumerable
,IEquatable
, etc.