Classi (Visual C# Express)
Aggiornamento: novembre 2007
C# è un linguaggio di programmazione orientato a oggetti che, analogamente ad altri linguaggi moderni, raggruppa campi, metodi, proprietà ed eventi correlati in strutture di dati denominate classi.
Confronto tra classi e oggetti
Una classe è fondamentalmente un progetto iniziale per un tipo di dati personalizzato. Una volta definita, è possibile utilizzarla caricandola in memoria. Una classe caricata in memoria rappresenta un oggetto o un'istanza. È possibile creare un'istanza di una classe utilizzando la parola chiave new di C#.
Di seguito viene presentato un esempio di definizione di una classe denominata SampleClass e viene illustrata la creazione di un oggetto denominato sampleClass1 che rappresenta un'istanza di tale classe. Poiché in C# è necessario definire la funzione Main all'interno di una classe, il codice riportato di seguito consente inoltre di definire una classe Program, che tuttavia non viene utilizzata per creare un oggetto.
using System;
class SampleClass
{
public void SayHello()
{
Console.WriteLine("Hello, World!");
}
}
class Program
{
//Main is the entrypoint, where every C# program starts
static void Main(string[] args)
{
SampleClass sampleClass1 = new SampleClass(); // Create an object
sampleClass1.SayHello(); // Call a method
}
}
Così come è possibile costruire un numero qualsiasi di edifici sulla base di un unico progetto iniziale, è possibile creare un'istanza di qualsiasi numero di oggetti della stessa classe. Molto spesso sono presenti matrici o elenchi che contengono molti oggetti della stessa classe. Ciascuna istanza della classe occupa uno spazio distinto in memoria e i valori dei relativi campi sono distinti e indipendenti, ad eccezione di quelli statici descritti di seguito. Nell'esempio di codice riportato di seguito è possibile creare un oggetto di tipo Animal e impostarne le dimensioni su 2, quindi creare un altro oggetto impostandone le dimensioni su 3. Esiste tuttavia un'importante eccezione a questa regola, costituita dal membro statico.
Confronto tra membri statici e membri di istanza
Un membro statico è costituito da un metodo o da un campo accessibile senza fare riferimento a un'istanza specifica di una classe. Il metodo statico più comune è Main, che corrisponde al punto di ingresso per tutti i programmi C#. Si noti che, per chiamare il metodo Main, non è necessario creare un'istanza della classe che lo contiene. Un altro metodo statico molto frequente è WriteLine, utilizzato nella classe Console. È utile sottolineare la differente sintassi per l'accesso ai metodi statici. A sinistra dell'operatore punto (.) viene infatti utilizzato il nome della classe e non dell'istanza: Console.WriteLine.
Un campo di classe dichiarato come statico verrà condiviso tra tutte le istanze di tale classe. Se nell'esempio riportato di seguito si dichiara come statico il campo size e viene modificato il valore di un oggetto Animal, il valore verrà modificato per tutti gli oggetti di tipo Animal.
Una classe statica è costituita esclusivamente da membri statici. Classi, metodi e campi statici risultano utili in alcuni scenari per ottimizzare prestazioni ed efficienza. È tuttavia possibile riscontrare errori insidiosi se si presuppone che un campo sia di tipo istanza mentre in realtà è statico. Per ulteriori informazioni, vedere Classi statiche e membri di classi statiche (Guida per programmatori C#).
Confronto tra classi e file
Ogni programma C# dispone di almeno una classe. Durante la progettazione del programma, è consigliabile, ma non necessario, mantenere un'unica classe in ciascun file di codice sorgente con estensione cs. Se si utilizza l'ambiente di sviluppo integrato (IDE, Integrated Development Environment) di C# per creare le classi, contemporaneamente, verrà creato un nuovo file di codice sorgente in modo automatico.
Incapsulamento
Una classe rappresenta in genere le caratteristiche di un oggetto e le operazioni che è in grado di eseguire. Per rappresentare, ad esempio, un animale sotto forma di classe C#, è possibile specificare caratteristiche quali dimensioni, velocità e forza rappresentate da valori numerici, nonché alcune funzioni quali MoveLeft(), MoveRight(), SpeedUp(), Stop() e così via, in cui scrivere il codice che consenta all'"animale" di eseguire tali operazioni. In C# la classe relativa all'animale sarà simile a quella riportata di seguito:
public class Animal
{
private int size;
private float speed;
private int strength;
public void MoveLeft() // method
{
// code goes here...
}
// other methods go here...
}
Sfogliando .NET Framework Class Library, si noterà che ciascuna classe rappresenta un oggetto, ad esempio XmlDocument, String, Form e che per ciascun oggetto sono disponibili diverse operazioni eseguibili (metodi), caratteristiche che è possibile leggere ed eventualmente modificare (proprietà), nonché notifiche (eventi) inviate quando vengono eseguite alcune operazioni specifiche. I metodi, le proprietà e gli eventi, unitamente a tutte le altre variabili e costanti interne (campi), costituiscono i membri della classe.
Il raggruppamento di membri in classi non è solo logico ma consente di nascondere dati e funzioni che si desidera rendere inaccessibili ad altro codice. Questo principio è noto come incapsulamento. Quando si sfogliano le librerie di classi .NET Framework, vengono visualizzati solo i membri pubblici di tali classi. È invece possibile che ciascuna classe contenga anche membri privati utilizzati internamente dalla classe o dalle classi ad essa correlate, ma non destinati all'utilizzo nelle applicazioni. Quando si creano classi personalizzate, si decide quali membri dovranno essere pubblici e quali dovranno essere privati.
Ereditarietà
Una classe può ereditare un'altra classe e quindi includere tutti i membri, pubblici e privati, della classe originale, nonché i membri aggiuntivi da essa definiti. La classe originale è denominata classe base, mentre quella nuova rappresenta la classe derivata. Una classe derivata consente di rappresentare un tipo più specializzato di classe base. È ad esempio possibile definire una classe Cat che eredita da Animal. La classe Cat include non solo tutte le operazioni previste nella classe Animal, ma anche un'ulteriore operazione univoca. Il codice C# sarà simile al seguente:
public class Cat : Animal
{
public void Purr()
{
}
}
La notazione Cat : Animal indica che Cat eredita da Animal e che pertanto Cat include anche un metodo MoveLeft e tre variabili private size, speed e strength. Una classe SiameseCat, che eredita da Cat, conterrà tutti i membri di Cat nonché tutti i membri di Animal.
Polimorfismo
Nell'ambito della programmazione il termine polimorfismo si riferisce alla possibilità di utilizzare una classe derivata per ridefinire metodi ereditati da una classe base o eseguirne l'override. È possibile adottare questa tecnica quando è necessario eseguire un'operazione specifica in un metodo diverso o non definito nella classe base. Per poter essere valido per tutti gli animali, il metodo Animal.MoveLeft deve essere molto generico e probabilmente molto semplice, ad esempio simile a "modifica l'orientamento in modo che la testa dell'animale punti nella direzione X". Nella classe Cat tale metodo potrebbe non essere sufficiente. Potrebbe infatti essere necessario specificare in che modo un elemento della classe Cat muove le zampe e la coda quando si gira. Se inoltre è stata definita una classe Fish o Bird, sarà forse necessario eseguire l'override del metodo MoveLeft in modi diversi anche per ciascuna di tali classi. Il comportamento del metodo MoveLeft può essere personalizzato per classi specifiche, pertanto il codice che consente di creare la classe e chiamarne i relativi metodi non include un metodo distinto per ciascun animale esistente. Purché l'oggetto erediti da Amimal, nel codice chiamante è possibile limitarsi a chiamare il metodo MoveLeft per richiamare la versione personalizzata del metodo per l'oggetto.
Costruttori
Ogni classe dispone di un costruttore, ovvero di un metodo che condivide lo stesso nome della classe. Il costruttore viene chiamato quando si crea un oggetto basato sulla definizione della classe e imposta in genere i valori iniziali delle variabili definite nella classe. Tale operazione non è necessaria se i valori iniziali devono essere pari a zero per i tipi di dati numerici, a false per i tipi di dati booleani o a null per i tipi di riferimento, in quanto tali tipi di dati vengono inizializzati automaticamente.
È possibile definire costruttori con qualsiasi numero di parametri. I costruttori che non includono parametri rappresentano i costruttori predefiniti. Nell'esempio riportato di seguito vengono definiti e quindi utilizzati una classe con un costruttore predefinito e un costruttore che accetta una stringa:
class SampleClass
{
string greeting;
public SampleClass()
{
greeting = "Hello, World";
}
public SampleClass(string message)
{
greeting = message;
}
public void SayHello()
{
System.Console.WriteLine(greeting);
}
}
class Program
{
static void Main(string[] args)
{
// Use default constructor.
SampleClass sampleClass1 = new SampleClass();
sampleClass1.SayHello();
// Use constructor that takes a string parameter.
SampleClass sampleClass2 = new SampleClass("Hello, Mars");
sampleClass2.SayHello();
}
}
Overload dell'operatore
La creazione di metodi diversi con lo stesso nome, come nel caso di SampleClass() nell'esempio precedente, è detta overload. II metodo da utilizzare è noto al compilatore perché l'elenco degli eventuali argomenti disponibili viene fornito ogni volta che si crea un oggetto. L'overload contribuisce a rendere il codice più flessibile e leggibile.
Distruttori
È possibile che i programmatori che utilizzano il linguaggio C++ conoscano già i distruttori. Grazie al sistema di Garbage Collection automatico incluso in C#, è improbabile che sia necessario implementare un distruttore a meno che la classe non utilizzi risorse non gestite. Per ulteriori informazioni, vedere Distruttori (Guida per programmatori C#).
Strutture
Una struttura è per molti aspetti un tipo simile a una classe, ma non supporta l'ereditarietà. Per ulteriori informazioni, vedere Strutture (Visual C# Express).
Vedere anche
Attività
Procedura: chiamare un metodo su un oggetto (Visual C#)
Procedura: ereditare da una classe (Visual C#)
Concetti
Nozioni di base del linguaggio C#