Partilhar via


resumo (Referência C#)

O abstract modificador indica que o seu destino tem uma implementação em falta ou incompleta. Use o modificador abstract com classes, métodos, propriedades, indexadores e eventos. Use o abstract modificador em uma declaração de classe para indicar que uma classe se destina apenas a ser uma classe base de outras classes, não instanciada por conta própria. As classes não abstratas que derivam da classe abstrata devem implementar membros marcados como abstratos.

A referência da linguagem C# documenta a versão mais recentemente lançada da linguagem C#. Contém também documentação inicial para funcionalidades em versões preliminares públicas para a próxima versão da linguagem.

A documentação identifica qualquer funcionalidade introduzida pela primeira vez nas últimas três versões da língua ou em pré-visualizações públicas atuais.

Sugestão

Para saber quando uma funcionalidade foi introduzida pela primeira vez em C#, consulte o artigo sobre o histórico de versões da linguagem C#.

As classes abstratas podem conter membros abstratos (que não têm implementação e devem ser substituídos em classes derivadas) e membros totalmente implementados (como métodos regulares, propriedades e construtores). Esta funcionalidade permite que classes abstratas forneçam funcionalidades comuns, exigindo ainda que classes derivadas implementem membros abstratos específicos.

Observação

Os membros da interface são abstract por defeito.

Classe abstrata com membros mistos

O exemplo a seguir demonstra uma classe abstrata que contém métodos implementados e membros abstratos:

namespace LanguageKeywords;

public abstract class Vehicle
{
    protected string _brand;
    
    // Constructor - implemented method in abstract class
    public Vehicle(string brand) => _brand = brand;
    
    // Implemented method - provides functionality that all vehicles share
    public string GetInfo() => $"This is a {_brand} vehicle.";
    
    // Another implemented method
    public virtual void StartEngine() => Console.WriteLine($"{_brand} engine is starting...");
    
    // Abstract method - must be implemented by derived classes
    public abstract void Move();
    
    // Abstract property - must be implemented by derived classes  
    public abstract int MaxSpeed { get; }
}

public class Car : Vehicle
{
    public Car(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} car is driving on the road.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 200;
}

public class Boat : Vehicle
{
    public Boat(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} boat is sailing on the water.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 50;
}

public class AbstractExample
{
    public static void Examples()
    {
        // Cannot instantiate abstract class: Vehicle v = new Vehicle("Generic"); // Error!
        
        Car car = new Car("Toyota");
        Boat boat = new Boat("Yamaha");
        
        // Using implemented methods from abstract class
        Console.WriteLine(car.GetInfo());
        car.StartEngine();
        
        // Using abstract methods implemented in derived class
        car.Move();
        Console.WriteLine($"Max speed: {car.MaxSpeed} km/h");
        
        Console.WriteLine();
        
        Console.WriteLine(boat.GetInfo());
        boat.StartEngine();
        boat.Move();
        Console.WriteLine($"Max speed: {boat.MaxSpeed} km/h");
    }
}

class Program
{
    static void Main()
    {
        AbstractExample.Examples();
    }
}
/* Output:
This is a Toyota vehicle.
Toyota engine is starting...
Toyota car is driving on the road.
Max speed: 200 km/h

This is a Yamaha vehicle.
Yamaha engine is starting...
Yamaha boat is sailing on the water.
Max speed: 50 km/h
*/

Neste exemplo, a Vehicle classe abstrata fornece:

  • Membros implementados: GetInfo() método, StartEngine() método e construtor - estes membros fornecem funcionalidades comuns para todos os veículos.
  • Membros do resumo: Move() método e MaxSpeed propriedade - estes elementos devem ser implementados por cada tipo específico de veículo.

Esse design permite que a classe abstrata forneça funcionalidade compartilhada, garantindo que as classes derivadas implementem um comportamento específico do veículo.

Classe concreta derivada de uma classe abstrata

Neste exemplo, a classe Square deve fornecer uma implementação de GetArea porque deriva de Shape:

abstract class Shape
{
    public abstract int GetArea();
}

class Square : Shape
{
    private int _side;

    public Square(int n) => _side = n;

    // GetArea method is required to avoid a compile-time error.
    public override int GetArea() => _side * _side;

    static void Main()
    {
        var sq = new Square(12);
        Console.WriteLine($"Area of the square = {sq.GetArea()}");
    }
}
// Output: Area of the square = 144

As aulas abstratas têm as seguintes características:

  • Não se pode criar uma instância de uma classe abstrata.
  • Uma classe abstrata pode conter métodos e acessores abstratos.
  • Uma classe abstrata também pode conter métodos implementados, propriedades, campos e outros membros que fornecem funcionalidade para classes derivadas.
  • Não podes usar o sealed modificador numa classe abstrata porque os dois modificadores têm significados opostos. O sealed modificador impede que uma classe seja herdada e o abstract modificador requer que uma classe seja herdada.
  • Uma classe não-abstrata derivada de uma classe abstrata deve incluir implementações reais de todos os métodos abstratos herdados e acessadores.

Use o abstract modificador num método ou declaração de propriedade para indicar que o método ou propriedade não contém implementação.

Os métodos abstratos têm as seguintes características:

  • Um método abstrato é implicitamente um método virtual.

  • As declarações de método abstrato só são permitidas em classes abstratas.

  • Como uma declaração abstrata de método não fornece uma implementação real, não existe corpo de método. A declaração do método termina simplesmente com ponto e vírgula. Por exemplo:

    public abstract void MyMethod();
    

    A implementação é fornecida por um método override, que é membro de uma classe não abstrata.

  • É um erro usar os static modificadores ou virtual numa declaração de método abstrato num class tipo. Podes declarar static abstract e static virtual métodos em interfaces.

    As propriedades abstratas se comportam como métodos abstratos, exceto pelas diferenças na sintaxe de declaração e invocação.

  • É um erro usar o abstract modificador numa propriedade estática num class tipo. Podes declarar static abstract propriedades de OR static virtual nas declarações de interface.

  • Uma propriedade herdada abstrata pode ser sobreposta numa classe derivada ao incluir uma declaração de propriedade que utiliza o override modificador.

Para obter mais informações sobre classes abstratas, consulte Classes abstratas e seladas e Membros da classe.

Uma classe abstrata deve fornecer implementação para todos os membros da interface. Uma classe abstrata que implementa uma interface pode mapear os métodos de interface em métodos abstratos. Por exemplo:

interface I
{
    void M();
}

abstract class C : I
{
    public abstract void M();
}

No exemplo seguinte, a classe DerivedClass deriva de uma classe BaseClassabstrata . A classe abstrata contém um método abstrato, AbstractMethode duas propriedades abstratas, X e Y.

// Abstract class
abstract class BaseClass
{
    protected int _x = 100;
    protected int _y = 150;

    // Abstract method
    public abstract void AbstractMethod();

    // Abstract properties
    public abstract int X { get; }
    public abstract int Y { get; }
}

class DerivedClass : BaseClass
{
    public override void AbstractMethod()
    {
        _x++;
        _y++;
    }

    public override int X   // overriding property
    {
        get
        {
            return _x + 10;
        }
    }

    public override int Y   // overriding property
    {
        get
        {
            return _y + 10;
        }
    }

    static void Main()
    {
        var o = new DerivedClass();
        o.AbstractMethod();
        Console.WriteLine($"x = {o.X}, y = {o.Y}");
    }
}
// Output: x = 111, y = 161

No exemplo anterior, se você tentar instanciar a classe abstrata usando uma instrução como esta:

BaseClass bc = new BaseClass();   // Error

Recebes um erro a dizer que o compilador não consegue criar uma instância da classe abstrata 'BaseClass'. No entanto, pode usar um construtor de classes abstratas, como mostrado no exemplo seguinte.

public abstract class Shape
{
    public string Color { get; set; }

    // Constructor of the abstract class
    protected Shape(string color)
    {
        Color = color;
        Console.WriteLine($"Created a shape with color {color}.");
    }

    // Abstract method that must be implemented by derived classes
    public abstract double CalculateArea();
}

public class Square : Shape
{
    public double Side { get; set; }

    // Constructor of the derived class calling the base class constructor
    public Square(string color, double side) : base(color)
    {
        Side = side;
    }

    public override double CalculateArea()
    {
        return Side * Side;
    }
}

public class Program
{
    public static void Main(string[] args)
     {
            Square square = new Square("red", 5);
            Console.WriteLine($"Area of the square: {square.CalculateArea()}");            
     }
}

A Shape classe é declarada abstract, o que significa que não podes instancia-la diretamente. Em vez disso, serve como um modelo para outras classes.

  • Mesmo que você não possa criar objetos de uma classe abstrata, ela ainda pode ter um construtor. Este construtor é tipicamente protected, o que significa que apenas classes derivadas podem aceder a ele. Nesse caso, o construtor Shape usa um parâmetro color e inicializa a propriedade Color. Ele também imprime uma mensagem para o console. A parte public Square(string color, double side) : base(color) chama o construtor da classe base (Shape) e passa o argumento color para ele.
  • Na Shape classe, o construtor definido toma uma cor como parâmetro protected Shape(string color). Isto significa que o C# já não fornece automaticamente um construtor sem parâmetros por defeito. As classes derivadas devem usar a : base(color) expressão para invocar o construtor base. Definir o valor padrão para color protected Shape(string color="green") permite omitir a : base(color) expressão nas classes derivadas. O construtor protected Shape(string color="green") define a cor para verde.

Especificação da linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso do C#.

Consulte também