latitude e longitude) e faz a estimativa. Por simplicidade, no nosso exemplo, eu fiz o calculo tracando uma linha reta e usando o teorema de Pitagoras, mas sabemos que na vida real um carro percorre ruas e avenidas fugindo do transito, entao um sistema real a estimativa de distancia seria mais apurada.Ja quando adicionamos a classe Taxi neste sistema, alem da distancia tambem calculamos a estimativa de custo que esse trajeto trara para o usuario. Fazemos isso no mesmo metodo CalcularEstimativas. Novamente por simplicidade eu considerei como resultado da conta um valor inicial da bandeirada de R$ 4,50 mais R$ 2,75 de cada unidade de distancia percorrida.Vejam o que acontece no cliente, representado aqui pelo metodo DeveCalcularEstimativaDistancia. Nao importa se eu passo um objeto do tipo Carro ou Taxi, a funcionalidade nao vai quebrar! Neste caso, a pos condicao da classe Taxi nao se enfraqueceu. A classe Carro calcula a distancia e a classe Taxi calcula a distancia e o preco, ou seja, ela faz uma coisa a mais. A substituicao de objetos ocorre sem problemas aqui, demonstrando que este exemplo agora atende o principio de Liskov.using System;using Microsoft.VisualStudio.TestTools.UnitTesting;namespace LiskovOk{ public struct Coordenada { public double Latitude; public double Longitude; public Coordenada(double latitude, double longitude) { Latitude = latitude; Longitude = longitude; } } public class Carro { public double Distancia { get; set; } public virtual void CalcularEstimativas(Coordenada pontoInicial, Coordenada pontoFinal) { double cateto1 = pontoFinal.Latitude - pontoInicial.Latitude; double cateto1AoQuadrado = Math.Pow(cateto1, 2); double cateto2 = pontoFinal.Longitude - pontoInicial.Longitude; double cateto2AoQuadrado = Math.Pow(cateto2, 2); Distancia = Math.Sqrt(cateto1AoQuadrado + cateto2AoQuadrado); } } public class Taxi : Carro { public double Valor { get; set; } public override void CalcularEstimativas(Coordenada pontoInicial, Coordenada pontoFinal) { base.CalcularEstimativas(pontoInicial, pontoFinal); Valor = 4.5 + Distancia * 2.75; } } [TestClass] public class UnitTest1 { [TestMethod] public void DeveCalcularEstimativaDistanciaComCarro() { DeveCalcularEstimativaDistancia(new Carro()); } [TestMethod] public void DeveCalcularEstimativaDistanciaComTaxi() { DeveCalcularEstimativaDistancia(new Taxi()); } private void DeveCalcularEstimativaDistancia(Carro sut) { sut.CalcularEstimativas(new Coordenada(0, 0), new Coordenada(12, 9)); Assert.AreEqual(15, sut.Distancia); } }}A regra de Liskov e importante pois ela serve para confirmar se estamos fazendo um uso correto da heranca de classes, sempre olhando o contexto geral da aplicacao. Se nao atendermos este principio, pode ter certeza que alguma besteira esta sendo feita. Herdar uma classe somente para reaproveitar codigos utilitarios seria um exemplo de erro cometido.Toda heranca depende de um contexto. No primeiro exemplo, o contexto nao permite que se tenha subclasses visto que sao calculos totalmente diferentes, nao estao relacionados.Lembre-se sempre de ponderar bem quando se esta usando heranca: se as pre condicoes nao estao sendo fortificadas; se as pos condicoes nao estao sendo enfraquecidas. So dessa maneira podemos deixar o sistema melhor desenhado, o que reflete melhor o negocio que ele atende e facilita as manutencoes futuras.Mais para frente eu pretendo comentar de outros principios do SOLID. Ate a proxima!