Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Il abstract modificatore indica che la destinazione ha un'implementazione mancante o incompleta. Usare il modificatore astratto 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. Le classi non astratte che derivano dalla classe astratta devono implementare membri contrassegnati come astratti.
Il riferimento al linguaggio C# documenta la versione rilasciata più di recente del linguaggio C#. Contiene anche la documentazione iniziale per le funzionalità nelle versioni di anteprima pubblica per la prossima versione del linguaggio di programmazione.
La documentazione identifica tutte le funzionalità introdotte nelle ultime tre versioni della lingua o nelle anteprime pubbliche correnti.
Suggerimento
Per trovare quando una funzionalità è stata introdotta per la prima volta in C#, vedere l'articolo sulla cronologia delle versioni del linguaggio C#.
Le classi astratte possono contenere entrambi i membri astratti (che non hanno implementazione e devono essere sottoposti a override nelle classi derivate) e membri completamente implementati (ad esempio metodi regolari, proprietà e costruttori). Questa funzionalità consente alle classi astratte di fornire funzionalità comuni, pur richiedendo classi derivate per implementare membri astratti specifici.
Annotazioni
I membri dell'interfaccia sono abstract per impostazione predefinita.
Classe astratta con membri misti
Nell'esempio seguente viene illustrata una classe astratta che contiene sia metodi implementati che membri astratti:
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
*/
In questo esempio la Vehicle classe astratta fornisce:
-
Membri implementati:
GetInfo()metodo,StartEngine()metodo e costruttore: questi membri forniscono funzionalità comuni per tutti i veicoli. -
Membri astratti:
Move()metodo eMaxSpeedproprietà: questi membri devono essere implementati da ogni tipo di veicolo specifico.
Questa progettazione consente alla classe astratta di fornire funzionalità condivise garantendo al tempo stesso che le classi derivate implementino un comportamento specifico del veicolo.
Classe concreta derivata da una classe astratta
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 metodi astratti e funzioni di accesso.
- Una classe astratta può anche contenere metodi, proprietà, campi e altri membri implementati che forniscono funzionalità alle classi derivate.
- Non è possibile usare il
sealedmodificatore in una classe astratta perché i due modificatori hanno significati opposti. Il modificatoresealedimpedisce a una classe che venga ereditata e il modificatoreabstractrichiede 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 abstract modificatore in una dichiarazione di metodo o proprietà per indicare che il metodo o la proprietà non contiene l'implementazione.
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 metodo astratto non fornisce alcuna implementazione effettiva, non esiste alcun corpo del metodo. La dichiarazione del metodo termina semplicemente con un punto e virgola. Ad esempio:
public abstract void MyMethod();L'implementazione viene fornita da un metodo
override, che è un membro di una classe non astratta.È un errore usare i
staticmodificatori ovirtualin una dichiarazione di metodo astratto in unclasstipo. È possibile dichiararestatic abstractmetodi estatic virtualnelle interfacce.Le proprietà astratte si comportano come i metodi astratti, ad eccezione delle differenze nella sintassi di dichiarazione e di chiamata.
Si tratta di un errore per usare il
abstractmodificatore in una proprietà statica in unclasstipo. È possibile dichiararestatic abstractostatic virtualproprietà nelle dichiarazioni di interfaccia.È possibile eseguire l'override di una proprietà ereditata astratta in una classe derivata includendo una dichiarazione di proprietà che usa il
overridemodificatore.
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();
}
Nell'esempio seguente la classe DerivedClass deriva da una classe BaseClassastratta . 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
Viene visualizzato un errore che indica che il compilatore non può creare un'istanza della classe astratta 'BaseClass'. Tuttavia, è possibile usare un costruttore di classe astratta, come illustrato nell'esempio seguente.
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 Shape classe è dichiarata abstract, il che significa che non è possibile crearne 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
protectedgenere , ovvero solo le classi derivate possono accedervi. In questo caso, il costruttoreShapeaccetta un parametrocolore inizializza la proprietàColor. Stampa anche un messaggio nella console. La partepublic Square(string color, double side) : base(color)chiama il costruttore della classe base (Shape) e passa l'argomentocolora quest'ultimo. -
ShapeNella classe il costruttore definito accetta un colore come parametroprotected Shape(string color). Ciò significa che C# non fornisce più automaticamente un costruttore senza parametri predefinito. Le classi derivate devono usare l'espressione: base(color)per richiamare il costruttore di base. L'impostazione del valore predefinito su colorprotected Shape(string color="green")consente di omettere l'espressione: base(color)nelle classi derivate. Il costruttoreprotected Shape(string color="green")imposta 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#.