Resumo : neste tutorial, você aprenderá sobre o princípio de substituição de Liskov em C# e como aplicá-lo para construir aplicativos de software mais escaláveis e de fácil manutenção.
Introdução ao Princípio de Substituição C# Liskov
O princípio de substituição de Liskove (LSP) é o terceiro princípio dos princípios SOLID de design orientado a objetos:
- Princípio de Responsabilidade Única (SRP)
- Princípio Aberto-Fechado (OCP)
- Princípio de Substituição de Liskov (LSP)
- Princípio de segregação de interface (ISP)
- Princípio de Inversão de Dependência (DIP)
Observe que o princípio da substituição de Liskov recebeu o nome de Barbara Liskov , que o formulou pela primeira vez em 1988.
O princípio de substituição de Liskov afirma que se um método usa uma classe base , então ele deve ser capaz de usar qualquer uma de suas classes derivadas sem a necessidade de ter informações sobre a classe derivada.
Em outras palavras, as classes derivadas devem ser substituíveis por sua classe base sem causar erros ou efeitos colaterais. Isto significa que o comportamento da classe derivada não deve contradizer o comportamento da classe base.
Vamos dar um exemplo para entender o princípio de substituição de Liskov em C#:
namespace LSP;
public abstract class Vehicle
{
public abstract void Drive();
}
public class Car : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a car");
}
public class Truck : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a truck");
}
public class Program
{
public static void TestDrive(Vehicle vehicle)
{
vehicle.Drive();
}
public static void Main(string[] args)
{
var car = new Car();
TestDrive(car);
var truck = new Truck();
TestDrive(truck);
}
}
Linguagem de código: C# ( cs )
Como funciona.
Primeiro, defina uma classe abstrata Vehicle
que possua um Drive()
método abstrato:
public abstract class Vehicle
{
public abstract void Drive();
}
Linguagem de código: C# ( cs )
Segundo, defina as classes Car
e Truck
que herdam da Vehicle
classe. O Drive()
método em cada classe exibe uma mensagem no console:
public class Car : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a car");
}
public class Truck : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a truck");
}
Linguagem de código: C# ( cs )
Terceiro, defina o TestDrive()
método estático na Program
classe que usa a Vehicle
como parâmetro. O TestDrive()
método estático chama o Drive()
método do objeto veículo:
public class Program
{
public static void TestDrive(Vehicle vehicle)
{
vehicle.Drive();
}
// ...
}
Linguagem de código: C# ( cs )
Finalmente, passe uma instância de uma Car
classe para o TestDrive()
método estático, que chama o Drive()
método do Car
objeto. Da mesma forma, passe uma instância da Truck
classe para o TestDrive()
método estático, que chama o Drive()
método do truck
objeto:
public class Program
{
// ...
public static void Main(string[] args)
{
var car = new Car();
TestDrive(car);
var truck = new Truck();
TestDrive(truck);
}
}
Linguagem de código: C# ( cs )
Este é um exemplo do princípio da substituição de Liskov em ação. Podemos usar os objetos Car
e Truck
no TestDrive()
método sem causar erros.
Em outras palavras, podemos substituir as classes derivadas ( Car
& Truck
) por sua classe base ( Vehicle
) no TestDrive()
método.
Agora, vamos violar o princípio de substituição de Liskov introduzindo uma nova classe derivada chamada Aircraft
. Como você só pode pilotar uma aeronave, e não dirigi-la, o Drive()
método da Aircraft
classe gera uma exceção NotImplementedException
:
public class Aircraft : Vehicle
{
public override void Drive() => throw new NotImplementedException();
}
Linguagem de código: C# ( cs )
Quando passamos uma instância do Aircraft
objeto para o TestDrive()
método, isso cria um efeito colateral (ou uma exceção)
Como não podemos substituir the Aircraft
por sua classe base Vehicle
no TestDrive()
método, ele viola o princípio de substituição de Liskov.
O seguinte mostra todo o programa que viola o princípio de substituição de Liskov:
namespace LSP;
public abstract class Vehicle
{
public abstract void Drive();
}
public class Car : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a car");
}
public class Truck : Vehicle
{
public override void Drive() => Console.WriteLine("Drive a truck");
}
public class Aircraft : Vehicle
{
public override void Drive() => throw new NotImplementedException();
}
public class Program
{
public static void TestDrive(Vehicle vehicle)
{
vehicle.Drive();
}
public static void Main(string[] args)
{
var car = new Car();
TestDrive(car);
var truck = new Truck();
TestDrive(truck);
var aircraft = new Aircraft();
TestDrive(aircraft); // side effect
}
}
Linguagem de código: C# ( cs )
Resumo
- O princípio de substituição de Liskov afirma que as classes derivadas devem ser substituíveis por sua classe base sem causar erros.