Ereditarietà (Guida per programmatori C#)Inheritance (C# Programming Guide)

L'ereditarietà, insieme all'incapsulamento e al polimorfismo, rappresenta una delle tre principali caratteristiche (o pilastri) della programmazione orientata a oggetti.Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. L'ereditarietà consente di creare nuove classi che riusano, estendono e modificano il comportamento definito in altre classi.Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. La classe i cui membri vengono ereditati è denominata classe di base, mentre la classe che eredita tali membri è denominata classe derivata.The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. Una classe derivata può avere una sola classe di base diretta.A derived class can have only one direct base class. L'ereditarietà, tuttavia, è transitiva.However, inheritance is transitive. Se la classe C viene derivata dalla classe B e la classe B viene derivata dalla classe A, la classe C eredita i membri dichiarati nella classe B e nella classe A.If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Nota

Gli struct non supportano l'ereditarietà, mentre possono implementare interfacce.Structs do not support inheritance, but they can implement interfaces. Per altre informazioni, vedere Interfacce.For more information, see Interfaces.

Concettualmente, una classe derivata rappresenta una specializzazione della classe di base.Conceptually, a derived class is a specialization of the base class. Ad esempio, avendo una classe di base Animal, è possibile definire una classe derivata denominata Mammal e un'altra classe derivata denominata Reptile.For example, if you have a base class Animal, you might have one derived class that is named Mammal and another derived class that is named Reptile. Un oggetto Mammal è anche un oggetto Animal e un oggetto Reptile è anche un Animal, ma ogni classe derivata rappresenta una diversa specializzazione della classe di base.A Mammal is an Animal, and a Reptile is an Animal, but each derived class represents different specializations of the base class.

Quando si definisce una classe derivandola da un'altra classe, la classe derivata acquista implicitamente tutti i membri della classe di base, con l'eccezione dei costruttori e dei finalizzatori.When you define a class to derive from another class, the derived class implicitly gains all the members of the base class, except for its constructors and finalizers. Di conseguenza, la classe derivata può riusare il codice definito nella classe di base senza doverlo implementare nuovamente.The derived class can thereby reuse the code in the base class without having to re-implement it. Nella classe derivata è possibile aggiungere altri membri.In the derived class, you can add more members. In questo modo, la classe derivata estende la funzionalità della classe di base.In this manner, the derived class extends the functionality of the base class.

La figura riportata di seguito illustra una classe WorkItem che rappresenta un elemento di lavoro in un qualche processo aziendale.The following illustration shows a class WorkItem that represents an item of work in some business process. Come per tutte le classi, è derivata da System.Object ed eredita tutti i metodi di tale classe.Like all classes, it derives from System.Object and inherits all its methods. WorkItem aggiunge cinque propri membri,WorkItem adds five members of its own. tra i quali un costruttore, perché i costruttori non vengono ereditati.These include a constructor, because constructors are not inherited. La classe ChangeRequest eredita da WorkItem e rappresenta un particolare tipo di elemento di lavoro.Class ChangeRequest inherits from WorkItem and represents a particular kind of work item. ChangeRequest aggiunge altri due membri ai membri che eredita da WorkItem e da Object.ChangeRequest adds two more members to the members that it inherits from WorkItem and from Object. Deve aggiungere il proprio costruttore e aggiunge anche originalItemID.It must add its own constructor, and it also adds originalItemID. La proprietà originalItemID consente l'associazione dell'istanza di ChangeRequest all'oggetto WorkItem originale a cui si applica la richiesta di modifica.Property originalItemID enables the ChangeRequest instance to be associated with the original WorkItem to which the change request applies.

Diagramma che illustra l'ereditarietà delle classi

Nell'esempio seguente viene illustrato come le relazioni tra le classi mostrate nella precedente illustrazione vengono espresse in C#.The following example shows how the class relationships demonstrated in the previous illustration are expressed in C#. Nell'esempio viene descritto anche come WorkItem esegue l'override del metodo virtuale Object.ToString e come la classe ChangeRequest eredita l'implementazione del metodo propria della classe WorkItem.The example also shows how WorkItem overrides the virtual method Object.ToString, and how the ChangeRequest class inherits the WorkItem implementation of the method.

// WorkItem implicitly inherits from the Object class.
public class WorkItem
{
    // Static field currentID stores the job ID of the last WorkItem that
    // has been created.
    private static int currentID;

    //Properties.
    protected int ID { get; set; }
    protected string Title { get; set; }
    protected string Description { get; set; }
    protected TimeSpan jobLength { get; set; }

    // Default constructor. If a derived class does not invoke a base-
    // class constructor explicitly, the default constructor is called
    // implicitly. 
    public WorkItem()
    {
        ID = 0;
        Title = "Default title";
        Description = "Default description.";
        jobLength = new TimeSpan();
    }

    // Instance constructor that has three parameters.
    public WorkItem(string title, string desc, TimeSpan joblen)
    {
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = joblen;
    }

    // Static constructor to initialize the static member, currentID. This
    // constructor is called one time, automatically, before any instance
    // of WorkItem or ChangeRequest is created, or currentID is referenced.
    static WorkItem()
    {
        currentID = 0;
    }


    protected int GetNextID()
    {
        // currentID is a static field. It is incremented each time a new
        // instance of WorkItem is created.
        return ++currentID;
    }

    // Method Update enables you to update the title and job length of an
    // existing WorkItem object.
    public void Update(string title, TimeSpan joblen)
    {
        this.Title = title;
        this.jobLength = joblen;
    }

    // Virtual method override of the ToString method that is inherited
    // from System.Object.
    public override string ToString()
    {
        return $"{this.ID} - {this.Title}";
    }
}

// ChangeRequest derives from WorkItem and adds a property (originalItemID) 
// and two constructors.
public class ChangeRequest : WorkItem
{
    protected int originalItemID { get; set; }

    // Constructors. Because neither constructor calls a base-class 
    // constructor explicitly, the default constructor in the base class
    // is called implicitly. The base class must contain a default 
    // constructor.

    // Default constructor for the derived class.
    public ChangeRequest() { }

    // Instance constructor that has four parameters.
    public ChangeRequest(string title, string desc, TimeSpan jobLen,
                         int originalID)
    {
        // The following properties and the GetNexID method are inherited 
        // from WorkItem.
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = jobLen;

        // Property originalItemId is a member of ChangeRequest, but not 
        // of WorkItem.
        this.originalItemID = originalID;
    }
}

class Program
{
    static void Main()
    {
        // Create an instance of WorkItem by using the constructor in the 
        // base class that takes three arguments.
        WorkItem item = new WorkItem("Fix Bugs",
                                     "Fix all bugs in my code branch",
                                     new TimeSpan(3, 4, 0, 0));

        // Create an instance of ChangeRequest by using the constructor in
        // the derived class that takes four arguments.
        ChangeRequest change = new ChangeRequest("Change Base Class Design",
                                                 "Add members to the class",
                                                 new TimeSpan(4, 0, 0),
                                                 1);

        // Use the ToString method defined in WorkItem.
        Console.WriteLine(item.ToString());

        // Use the inherited Update method to change the title of the 
        // ChangeRequest object.
        change.Update("Change the Design of the Base Class",
            new TimeSpan(4, 0, 0));

        // ChangeRequest inherits WorkItem's override of ToString.
        Console.WriteLine(change.ToString());

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    1 - Fix Bugs
    2 - Change the Design of the Base Class
*/

Metodi virtuali e astrattiAbstract and Virtual Methods

Quando una classe di base dichiara un metodo come virtual (virtuale), una classe derivata può eseguire l'override del metodo definendo una propria implementazione.When a base class declares a method as virtual, a derived class can override the method with its own implementation. Se una classe di base dichiara un membro come abstract (astratto), è necessario effettuare l'override di tale metodo in ogni classe non astratta che eredita direttamente da tale classe.If a base class declares a member as abstract, that method must be overridden in any non-abstract class that directly inherits from that class. Quando una classe derivata è essa stessa astratta, eredita i membri astratti senza implementarli.If a derived class is itself abstract, it inherits abstract members without implementing them. I membri astratti e virtuali costituiscono la base del polimorfismo, che rappresenta la seconda principale caratteristica della programmazione orientata a oggetti.Abstract and virtual members are the basis for polymorphism, which is the second primary characteristic of object-oriented programming. Per altre informazioni, vedere Polimorfismo.For more information, see Polymorphism.

Classi di base astratteAbstract Base Classes

Se si vuole evitare la generazione di istanze dirette di una classe, è possibile dichiarare una classe come abstract usando l'operatore new.You can declare a class as abstract if you want to prevent direct instantiation by using the new operator. In questo modo, la classe è utilizzabile soltanto quando una nuova classe viene derivata da essa.If you do this, the class can be used only if a new class is derived from it. Una classe astratta può contenere una o più firme di metodi, a loro volta dichiarate come astratte.An abstract class can contain one or more method signatures that themselves are declared as abstract. Tali firme specificano i parametri e il valore restituito, ma non definiscono alcuna implementazione (corpo del metodo).These signatures specify the parameters and return value but have no implementation (method body). Una classe astratta non deve necessariamente contenere membri astratti. Se però una classe contiene un membro astratto, deve essere dichiarata astratta.An abstract class does not have to contain abstract members; however, if a class does contain an abstract member, the class itself must be declared as abstract. Le classi derivate non definite come astratte esse stesse devono fornire l'implementazione per qualsiasi metodo astratto ereditato da una classe di base astratta.Derived classes that are not abstract themselves must provide the implementation for any abstract methods from an abstract base class. Per altre informazioni, vedere Classi e membri delle classi astratte e sealed.For more information, see Abstract and Sealed Classes and Class Members.

InterfacceInterfaces

Un'interfaccia rappresenta un tipo di riferimento ed è per vari aspetti simile a una classe di base astratta costituita solo da membri astratti.An interface is a reference type that is somewhat similar to an abstract base class that consists of only abstract members. Quando una classe implementa un'interfaccia, deve fornire un'implementazione per tutti i membri definiti nell'interfaccia.When a class implements an interface, it must provide an implementation for all the members of the interface. Una classe può implementare più interfacce, anche se può essere derivata solo da una singola classe di base diretta.A class can implement multiple interfaces even though it can derive from only a single direct base class.

Le interfacce sono usate per definire specifiche funzionalità per le classi che non sono necessariamente caratterizzate da una relazione di tipo "è un".Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. Ad esempio, l'interfaccia System.IEquatable<T> può essere implementata da qualunque classe o struct che debba abilitare il codice client per determinare se due oggetti di un dato tipo sono equivalenti, indipendentemente da come il tipo definisca l'equivalenza.For example, the System.IEquatable<T> interface can be implemented by any class or struct that has to enable client code to determine whether two objects of the type are equivalent (however the type defines equivalence). IEquatable<T> non implica lo stesso tipo di relazione "è" esistente tra una classe di base e una classe derivata. Ad esempio, un Mammal è un Animal.IEquatable<T> does not imply the same kind of "is a" relationship that exists between a base class and a derived class (for example, a Mammal is an Animal). Per altre informazioni, vedere Interfacce.For more information, see Interfaces.

Prevenzione di un'ulteriore derivazionePreventing Further Derivation

È possibile evitare che altre classi ereditino da una data classe o da uno qualsiasi dei suoi membri, dichiarando tale classe o tale membro come sealed.A class can prevent other classes from inheriting from it, or from any of its members, by declaring itself or the member as sealed. Per altre informazioni, vedere Classi e membri delle classi astratte e sealed.For more information, see Abstract and Sealed Classes and Class Members.

Nascondere un membro di una classe di base in una classe derivataDerived Class Hiding of Base Class Members

Una classe derivata può nascondere i membri di una classe di base dichiarando dei membri con lo stesso nome e la stessa firma.A derived class can hide base class members by declaring members with the same name and signature. Il modificatore new può essere usato per indicare in modo esplicito che un membro non costituisce un override del membro della classe di base.The new modifier can be used to explicitly indicate that the member is not intended to be an override of the base member. L'uso del modificatore new non è necessario. Tuttavia, se il modificatore new non viene usato, il compilatore genererà un avviso.The use of new is not required, but a compiler warning will be generated if new is not used. Per altre informazioni, vedere Controllo delle versioni con le parole chiave Override e New e Sapere quando usare le parole chiave Override e New.For more information, see Versioning with the Override and New Keywords and Knowing When to Use Override and New Keywords.

Vedere ancheSee also