Dziedziczenie (Przewodnik programowania w języku C#)Inheritance (C# Programming Guide)

Dziedziczenie, wraz z hermetyzacją i polimorfizmem, jest jedną z trzech podstawowych cech programowania zorientowanego obiektowo.Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. Dziedziczenie umożliwia tworzenie nowych klas, które będą używać, zwiększać i modyfikować zachowanie zdefiniowane w innych klasach.Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. Klasa, której członkowie są dziedziczone jest nazywana klasą bazową, a Klasa, która dziedziczy tych członków, nosi nazwę klasy pochodnej.The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. Klasa pochodna może mieć tylko jedną bezpośrednią klasę bazową.A derived class can have only one direct base class. Dziedziczenie jest jednak przechodnie.However, inheritance is transitive. Jeśli ClassC pochodzi z ClassB, a ClassB pochodzi od ClassA, ClassC dziedziczy składowe zadeklarowane w ClassB i ClassA.If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Uwaga

Struktury nie obsługują dziedziczenia, ale mogą implementować interfejsy.Structs do not support inheritance, but they can implement interfaces. Więcej informacji znajdziesz w artykule Interfejsy.For more information, see Interfaces.

Koncepcyjnie Klasa pochodna jest specjalizacją klasy bazowej.Conceptually, a derived class is a specialization of the base class. Na przykład jeśli masz klasę Animalbazową, może istnieć jedna klasa pochodna o nazwie Mammal i innej klasie pochodnej o nazwie 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. A to a, Reptile i jest Animal, ale każda klasa pochodna reprezentuje różne specjalizacje klasy bazowej. Mammal AnimalA Mammal is an Animal, and a Reptile is an Animal, but each derived class represents different specializations of the base class.

Podczas definiowania klasy, która ma pochodzić z innej klasy, Klasa pochodna niejawnie uzyskuje wszystkie elementy członkowskie klasy bazowej, z wyjątkiem konstruktorów i finalizatorów.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. Klasa pochodna może w efekcie ponownie użyć kodu w klasie bazowej bez konieczności jego ponownego wdrożenia.The derived class can thereby reuse the code in the base class without having to re-implement it. W klasie pochodnej można dodać więcej elementów członkowskich.In the derived class, you can add more members. W ten sposób Klasa pochodna rozszerza funkcjonalność klasy bazowej.In this manner, the derived class extends the functionality of the base class.

Na poniższej ilustracji przedstawiono klasę WorkItem , która reprezentuje element pracy w pewnym procesie biznesowym.The following illustration shows a class WorkItem that represents an item of work in some business process. Podobnie jak w przypadku wszystkich klas, System.Object pochodzi z i dziedziczy wszystkie metody.Like all classes, it derives from System.Object and inherits all its methods. WorkItemdodaje pięciu członków.WorkItem adds five members of its own. Należą do nich Konstruktor, ponieważ konstruktory nie są dziedziczone.These include a constructor, because constructors are not inherited. Klasa ChangeRequest dziedziczy z WorkItem i reprezentuje konkretny rodzaj elementu pracy.Class ChangeRequest inherits from WorkItem and represents a particular kind of work item. ChangeRequestdodaje dwóch więcej członków do członków, z WorkItem Objectktórych dziedziczy.ChangeRequest adds two more members to the members that it inherits from WorkItem and from Object. Musi dodać własnego konstruktora, a także dodaje originalItemID.It must add its own constructor, and it also adds originalItemID. Umożliwia skojarzenie wystąpienia z oryginałem WorkItem , do którego ma zastosowanie żądanie zmiany. ChangeRequest originalItemIDProperty originalItemID enables the ChangeRequest instance to be associated with the original WorkItem to which the change request applies.

Diagram przedstawiający dziedziczenie klas

Poniższy przykład pokazuje, jak relacje klas pokazane na poprzedniej ilustracji są wyrażone w C#.The following example shows how the class relationships demonstrated in the previous illustration are expressed in C#. W przykładzie pokazano również, WorkItem jak zastępuje metodę Object.ToStringwirtualną oraz WorkItem sposób, w ChangeRequest jaki Klasa dziedziczy implementację metody.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
*/

Metody abstrakcyjne i wirtualneAbstract and Virtual Methods

Gdy klasa bazowa deklaruje metodę jako wirtualną, Klasa pochodna może zastąpić metodę własną implementacją.When a base class declares a method as virtual, a derived class can override the method with its own implementation. Jeśli klasa bazowa deklaruje element członkowski jako abstrakcyjny, ta metoda musi zostać zastąpiona w dowolnej klasie nieabstrakcyjnej, która bezpośrednio dziedziczy z tej klasy.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. Jeśli klasa pochodna jest abstrakcyjna, dziedziczy abstrakcyjne elementy członkowskie bez wdrażania ich.If a derived class is itself abstract, it inherits abstract members without implementing them. Abstrakcyjne i wirtualne elementy członkowskie są podstawą dla polimorfizmu, który jest drugą podstawową cechą programowania zorientowanego obiektowo.Abstract and virtual members are the basis for polymorphism, which is the second primary characteristic of object-oriented programming. Aby uzyskać więcej informacji, zobacz polimorfizm.For more information, see Polymorphism.

Abstrakcyjne klasy podstawoweAbstract Base Classes

Można zadeklarować klasę jako abstrakcyjną , jeśli chcesz zapobiec bezpośredniemu tworzeniu wystąpienia przy użyciu operatora New .You can declare a class as abstract if you want to prevent direct instantiation by using the new operator. Jeśli to zrobisz, Klasa może być używana tylko wtedy, gdy nowa klasa pochodzi od niej.If you do this, the class can be used only if a new class is derived from it. Klasa abstrakcyjna może zawierać co najmniej jeden podpis metody, który sam jest zadeklarowany jako abstrakcyjny.An abstract class can contain one or more method signatures that themselves are declared as abstract. Te podpisy określają parametry i wartość zwracaną, ale nie mają implementacji (treść metody).These signatures specify the parameters and return value but have no implementation (method body). Klasa abstrakcyjna nie musi zawierać abstrakcyjnych elementów członkowskich; Jeśli jednak Klasa zawiera abstrakcyjną składową, sama klasa musi być zadeklarowana jako abstract.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. Klasy pochodne, które nie są abstrakcyjne, muszą dostarczać implementację dla wszelkich metod abstrakcyjnych z abstrakcyjnej klasy bazowej.Derived classes that are not abstract themselves must provide the implementation for any abstract methods from an abstract base class. Aby uzyskać więcej informacji, zobacz klasy abstrakcyjne i zapieczętowane oraz składowe klas.For more information, see Abstract and Sealed Classes and Class Members.

InterfejsyInterfaces

Interfejs jest typem referencyjnym, który jest nieco podobny do abstrakcyjnej klasy bazowej, która składa się tylko z abstrakcyjnych elementów członkowskich.An interface is a reference type that is somewhat similar to an abstract base class that consists of only abstract members. Gdy klasa implementuje interfejs, musi dostarczyć implementację dla wszystkich elementów członkowskich interfejsu.When a class implements an interface, it must provide an implementation for all the members of the interface. Klasa może zaimplementować wiele interfejsów, chociaż może dziedziczyć tylko z pojedynczej bezpośredniej klasy bazowej.A class can implement multiple interfaces even though it can derive from only a single direct base class.

Interfejsy służą do definiowania określonych funkcji dla klas, które nie muszą mieć relacji "is".Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. Na przykład System.IEquatable<T> interfejs może być zaimplementowany przez dowolną klasę lub strukturę, która musi umożliwić kod klienta, aby określić, czy dwa obiekty typu są równoważne (jednak typ definiuje równoważność).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>nie implikuje tego samego rodzaju relacji "is", która istnieje między klasą bazową a klasą pochodną (na przykład a Mammal 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). Więcej informacji znajdziesz w artykule Interfejsy.For more information, see Interfaces.

Zapobieganie dalszemu wyprowadzaniuPreventing Further Derivation

Klasa może uniemożliwić innym klasom dziedziczenie z niego lub z dowolnego elementu członkowskiego, deklarując siebie lub element członkowski jako zapieczętowany.A class can prevent other classes from inheriting from it, or from any of its members, by declaring itself or the member as sealed. Aby uzyskać więcej informacji, zobacz klasy abstrakcyjne i zapieczętowane oraz składowe klas.For more information, see Abstract and Sealed Classes and Class Members.

Ukrywanie klasy pochodnej elementów członkowskich klasy bazowejDerived Class Hiding of Base Class Members

Klasa pochodna może ukryć składowe klasy bazowej, deklarując składowe o tej samej nazwie i podpisie.A derived class can hide base class members by declaring members with the same name and signature. Przy użyciu nowego modyfikatora można jawnie wskazać, że element członkowski nie jest przesłonięciem podstawowego elementu członkowskiego.The new modifier can be used to explicitly indicate that the member is not intended to be an override of the base member. Korzystanie z nowych nie jest wymagane, ale jeśli nowe nie zostanie użyte, zostanie wygenerowane Ostrzeżenie kompilatora.The use of new is not required, but a compiler warning will be generated if new is not used. Aby uzyskać więcej informacji, zobacz przechowywanie wersji z zastępowaniem i nowymi słowami kluczowymi i wiedzą, kiedy używać przesłonięć i nowych słów kluczowych.For more information, see Versioning with the Override and New Keywords and Knowing When to Use Override and New Keywords.

Zobacz takżeSee also