Resumo : neste tutorial, você aprenderá quando usar uma classe abstrata e quando usar uma interface e as diferenças entre uma classe abstrata e uma interface.
Escolhendo entre uma classe abstrata e uma interface
Em C#, uma classe abstrata é semelhante a uma interface . No entanto, a classe abstrata e a interface servem a propósitos diferentes. Portanto, é importante saber quando usar uma classe abstrata e quando usar uma interface.
Geralmente, quando você deseja modelar o relacionamento é-um e compartilhar uma implementação comum com todas as subclasses, você usa uma classe abstrata.
Mas quando você deseja criar um contrato ao qual outras classes devem aderir, você usa uma interface.
O exemplo a seguir demonstra como usar a classe abstrata Shape que possui o método Display() compartilhado por todas as suas subclasses:
abstract class Shape
{
public abstract double GetArea();
public abstract double GetPerimeter();
public void Display()
{
Console.WriteLine($"Area: {GetArea():F2}, Perimeter: {GetPerimeter():F2}");
}
}
class Rectangle : Shape
{
readonly double length;
readonly double width;
public Rectangle(double length, double width)
{
this.length = length;
this.width = width;
}
public override double GetArea()
{
return length * width;
}
public override double GetPerimeter()
{
return 2 * (length + width);
}
}
class Circle : Shape
{
readonly double radius;
public Circle(double radius)
{
this.radius = radius;
}
public override double GetArea()
{
return Math.PI * radius * radius;
}
public override double GetPerimeter()
{
return 2 * Math.PI * radius;
}
}
class Program
{
static void Main(string[] args)
{
var shapes = new List<Shape>()
{
new Rectangle(5, 10),
new Circle(3)
};
foreach (var shape in shapes)
{
shape.Display();
}
}
}
Linguagem de código: C# ( cs )
Saída:
Area: 50.00, Perimeter: 30.00
Area: 28.27, Perimeter: 18.85
Linguagem de código: CSS ( css )
Neste exemplo, a Shape
classe é uma classe abstrata que define dois métodos abstratos GetArea
e GetPerimeter
. Qualquer classe que herda da classe Shape precisa implementar esses métodos.
A Shape
classe também possui um método concreto Display
que exibe a área e o perímetro de uma forma. Todas as subclasses da Shape
classe compartilharão o mesmo Display
método.
As classes Rectangle e Circle estendem a classe Shape. Ambas as classes compartilham a mesma implementação de Display
método, mas cada uma fornece sua própria implementação GetArea
e GetPerimeter
métodos.
O exemplo a seguir demonstra como usar uma interface como contrato:
interface ILogger
{
void Log(string message);
}
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
class FileLogger : ILogger
{
private readonly string filePath;
public FileLogger(string filePath)
{
this.filePath = filePath;
}
public void Log(string message)
{
using StreamWriter writer = new StreamWriter(filePath, true);
writer.WriteLine(message);
}
}
class Program
{
static void Main(string[] args)
{
ILogger logger;
if (args.Length > 0 && args[0] == "file")
{
logger = new FileLogger("log.txt");
}
else
{
logger = new ConsoleLogger();
}
logger.Log("Starting application...");
// ...
logger.Log("Application stopped.");
}
}
Linguagem de código: C# ( cs )
Neste exemplo, definimos a ILogger
interface que possui um único método Log
. O Log
método utiliza uma string que representa a mensagem a ser registrada.
As classes ConsoleLogger
e FileLogger
implementam a ILogger
interface e fornecem suas próprias implementações do Log
método.
No Main
método, criamos uma instância ConsoleLogger
ou FileLogger
com base no argumento da linha de comando.
Se o argumento for "file"
, criamos um FileLogger
objeto. Caso contrário, criamos um ConsoleLogger
objeto.
Independentemente de FileLogger
a ConsoleLogger
instância ter sido criada, chamamos o Log
método para registrar algumas mensagens
Como ambas FileLogger
as ConsoleLogger
classes implementam a mesma interface, podemos alternar facilmente entre elas em tempo de execução.
Classe abstrata vs. Interface
A tabela a seguir ilustra as diferenças entre classes abstratas e interfaces:
Aulas abstratas | Interfaces |
---|---|
Implementação compartilhada | Definir um contrato |
Só pode herdar de uma única classe base | Pode implementar qualquer número de interfaces |
Código de implementação irrestrito | Código de implementação limitado |
Pode ter propriedades automáticas | Sem propriedades automáticas |
Resumo
- Use uma classe abstrata para modelar um relacionamento é-um e compartilhe uma implementação comum com todas as subclasses.
- Use uma interface para representar um contrato ao qual outras classes devem aderir.