Condividi tramite


abstract (Riferimenti per C#)

Il modificatore abstract indica che l'oggetto in fase di modifica ha un'implementazione mancante o incompleta. Il modificatore abstract può essere usato con classi, metodi, proprietà, indicizzatori ed eventi. Usare il modificatore abstract in una dichiarazione di classe per indicare che una classe verrà usata solo come classe di base per altre classi e che non verrà creata un'istanza relativamente alla stessa. I membri contrassegnati come astratti devono essere implementati da classi non astratte che derivano dalla classe astratta.

Esempio 1

In questo esempio, la classe Square deve eseguire un'implementazione di GetArea poiché deriva da 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

Le classi astratte hanno le caratteristiche seguenti:

  • Non è possibile creare un'istanza di una classe astratta.

  • Una classe astratta può contenere funzioni di accesso e metodi astratti.

  • Non è possibile modificare una classe astratta con il modificatore sealed perché i due modificatori hanno significati opposti. Il modificatore sealed impedisce a una classe che venga ereditata e il modificatore abstract richiede una classe da ereditare.

  • Una classe non astratta derivata da una classe astratta deve includere implementazioni effettive di tutte le funzioni di accesso e di tutti i metodi astratti ereditati.

Usare il modificatore abstract in una dichiarazione di metodo o proprietà per indicare che il metodo o proprietà non contiene implementazioni.

I metodi astratti hanno le caratteristiche seguenti:

  • Un metodo astratto è implicitamente un metodo virtuale.

  • Le dichiarazioni di metodi astratti sono consentite solo in classi astratte.

  • Poiché una dichiarazione di un metodo astratto non offre alcuna implementazione effettiva, non c'è nessun corpo del metodo. La dichiarazione del metodo termina semplicemente con un punto e virgola e non ci sono parentesi graffe ({ }) dopo la firma. Ad esempio:

    public abstract void MyMethod();  
    

    L'implementazione viene specificata tramite l'override di un metodo, che è un membro di una classe non astratta.

  • Non è possibile usare il modificatore static o virtual in una dichiarazione di un metodo astratto.

Le proprietà astratte si comportano come i metodi astratti, ad eccezione delle differenze nella sintassi di dichiarazione e di chiamata.

  • Non è possibile usare il modificatore abstract su una proprietà static.

  • Una proprietà astratta ereditata può essere sottoposta a override in una classe derivata includendo una dichiarazione di proprietà che usa il modificatore di override.

Per altre informazioni sulle classi astratte, vedere Classi e membri delle classi astratte e sealed.

Una classe astratta deve specificare l'implementazione per tutti i membri di interfaccia.

Una classe astratta che implementa un'interfaccia può eseguire il mapping dei metodi di interfaccia su metodi astratti. Ad esempio:

interface I
{
    void M();
}

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

Esempio 2

In questo esempio, la classe DerivedClass è derivata da una classe di base astratta BaseClass. La classe astratta contiene un metodo astratto, AbstractMethod, e due proprietà astratte, 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

Nell'esempio precedente, se si prova a creare un'istanza della classe astratta tramite un'istruzione simile alla seguente:

BaseClass bc = new BaseClass();   // Error  

si ottiene un messaggio di errore che informa che il compilatore non può creare un'istanza della classe astratta "BaseClass".

Tuttavia, è possibile usare un costruttore di classe astratta, come nell'esempio seguente

Esempio 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()}");            
     }
}

La classe Shape viene dichiarata abstract, il che significa che non si può creare direttamente un'istanza. Funge invece da progetto per altre classi.

  • Anche se non è possibile creare oggetti di una classe astratta, può comunque avere un costruttore. Questo costruttore è in genere protected, ovvero è accessibile solo da classi derivate. In questo caso, il costruttore Shape accetta un parametro color e inizializza la proprietà Color. Stampa anche un messaggio nella console. La parte public Square(string color, double side) : base(color) chiama il costruttore della classe base (Shape) e passa l'argomento color a quest'ultimo.
  • Nella classe Shape, il costruttore specifico accetta un colore come parametro protected Shape(string color). Ciò significa che non esiste più un costruttore senza parametri predefinito fornito automaticamente da C# e pertanto le classi derivate devono usare l'espressione : base(color) per richiamare il costruttore di base. L'impostazione del valore predefinito al colore protected Shape(string color="green") consentirà di omettere l'espressione : base(color) nelle classi derivate. Tuttavia, il costruttore protected Shape(string color="green") verrà comunque richiamato, impostando il colore su verde.

Specifiche del linguaggio C#

Per altre informazioni, vedere la specifica del linguaggio C#. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.

Vedi anche