Compartilhar via


abstract (Referência de C#)

O modificador abstract indica que o item que está sendo modificado tem uma implementação ausente ou incompleta. O modificador abstrato pode ser usado com classes, métodos, propriedades, indexadores e eventos. Use o modificador abstract em uma declaração de classe para indicar que uma classe se destina somente a ser uma classe base de outras classes, não instanciada por conta própria. Membros marcados como abstratos precisam ser implementados por classes não abstratas que derivam da classe abstrata.

Exemplo 1

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 classes abstratas têm os seguintes recursos:

  • Uma classe abstrata não pode ser instanciada.

  • Uma classe abstrata pode conter acessadores e métodos abstratos.

  • Não é possível modificar uma classe abstrata com o modificador sealed porque os dois modificadores têm significados opostos. O modificador sealed impede que uma classe seja herdada e o modificador abstract requer uma classe a ser herdada.

  • Uma classe não abstrata derivada de uma classe abstrata deve incluir implementações reais de todos os acessadores e métodos abstratos herdados.

Use o modificador abstract em uma declaração de método ou propriedade para indicar que o método ou propriedade não contem a implementação.

Os métodos abstratos têm os seguintes recursos:

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

  • Declarações de método abstrato são permitidas apenas em classes abstratas.

  • Como uma declaração de método abstrato não fornece nenhuma implementação real, não há nenhum corpo de método, a declaração do método simplesmente termina com um ponto e vírgula e não há chaves ({ }) após a assinatura. Por exemplo:

    public abstract void MyMethod();  
    

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

  • É um erro usar os modificadores static ou virtual em uma declaração de método abstrato.

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

  • É um erro usar o modificador abstract em uma propriedade estática.

  • Uma propriedade herdada abstrata pode ser substituída em uma classe derivada incluindo uma declaração de propriedade que usa o modificador override.

Para obter mais informações sobre classes abstratas, consulte Classes e membros de classes abstratos e lacrados.

Uma classe abstrata deve fornecer uma implementação para todos os membros de 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();
}

Exemplo 2

Nesse exemplo, a classe DerivedClass é derivada de uma classe abstrata BaseClass. A classe abstrata contém um método abstrato, AbstractMethod e 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  

Você receberá uma mensagem de erro informando que o compilador não pode criar uma instância da classe abstrata "BaseClass".

No entanto, é possível usar um construtor de classe abstrato, como no exemplo abaixo

Exemplo 3

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 classe Shape é declarada abstract, o que significa que ela não pode ser instanciada diretamente. Em vez disso, ele 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. Esse construtor normalmente é protected, o que significa que ele só pode ser acessado de classes derivadas. Nesse caso, o construtor Shape usa um parâmetro color e inicializa a propriedade Color. Ele também imprime uma mensagem no 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 classe Shape, o construtor definido usa uma cor como um parâmetro protected Shape(string color). Isso significa que não há mais um construtor sem parâmetro padrão fornecido automaticamente pelo C#, portanto, as classes derivadas devem usar a expressão : base(color) para invocar o construtor base. Definir o valor padrão como cor protected Shape(string color="green") permitirá omitir a expressão : base(color) em classes derivadas, ainda assim, esse construtor protected Shape(string color="green") será invocado, definindo a cor como 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 de C#.

Confira também