Existe uma classe LinkedList com funções como add_first (), add_last (), add_after (), remove_first (), remove_last () e remove ()
Agora há uma classe Stack que fornece funcionalidades como push (), pop (), peek () ou top (), e para implementar esses métodos, ela estende os métodos da classe LinkedList. Isso é uma violação do princípio de substituição de Liskov?
Por exemplo, considere o caso add_after () para adicionar um nó na enésima posição de uma Lista vinculada. Isso pode ser feito na classe base, mas não na classe Stack. As pós-condições estão sendo enfraquecidas aqui ou você modifica o método add_after () para adicionar ao topo da pilha?
Além disso, se não for uma violação, esse design é ruim? E como você implementaria a funcionalidade Stack usando a classe LinkedList?
LinkedList
? Você pode querer seguir o conselho de um certo Joshua Bloch (que desempenhou um papel importante no design da estrutura de coleções Java) quando ele disse "Preferir composição sobre herança" - Talvez você tenha umaLinkedList
classe dentro de sua pilha, mas na verdade não a estende?LinkedList
que faz o trabalho pesado nos bastidores (composição). Dessa forma, os usuários do seu código não podem usar acidentalmente uma pilha onde precisavam de uma lista ou vice-versa.Respostas:
Não. É perfeitamente bom adicionar métodos em um subtipo.
Isso é uma violação do LSP. O LSP diz que instâncias de um subtipo devem ser substituíveis por instâncias de um supertipo sem alterar as propriedades desejáveis de um programa. Se um subtipo remover um método, qualquer código que chamar esse método falhará (ou obterá uma
NoMethodError
exceção ou algo nesse sentido). Claramente, "não travar" é uma propriedade desejável.Modificar o
add_after()
método dessa maneira é uma violação da regra de histórico (a mais importante das regras!) E, portanto, não ajuda a corrigir a violação do LSP.Usando composição.
NOTA: Tudo o que escrevi acima se aplica somente a idiomas que confundem subtipagem e subclasse! O LSP é sobre subtipagem , não subclassificação. Em um idioma que não confunda os dois, seria perfeitamente aceitável criar
Stack
uma subclasse deLinkedList
, contanto que você não o torne um subtipo deLinkedList
.fonte
Como tudo já foi abordado por Jörg W Mittag, apenas elaborei um pouco a seguinte parte:
Basicamente, quando há uma dúvida sobre se alguma hierarquia viola o LSP, isso depende do contrato que você representa. Então, qual contrato
add_after
tem? Se parecer, mesmo que louco, como "Adicionar um nó na n-ésima posição ou na parte superior", então você está bem, a pós-condição é atendida, o LSP não é violado. Caso contrário, é uma violação do LSP.fonte