Herança (Guia de Programação em C#)Inheritance (C# Programming Guide)

A herança, assim como o encapsulamento e o polimorfismo, é uma das três principais características da programação orientada ao objeto.Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. A herança permite que você crie novas classes que reutilizam, estendem e modificam o comportamento definido em outras classes.Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. A classe cujos membros são herdados é chamada classe base e a classe que herda esses membros é chamada classe derivada.The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. Uma classe derivada pode ter apenas uma classe base direta.A derived class can have only one direct base class. No entanto, a herança é transitiva.However, inheritance is transitive. Se ClassC for derivada de ClassB e ClassB for derivada de ClassA, ClassC herdará os membros declarados em ClassA e ClassB.If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Observação

Structs não dão suporte a herança, mas podem implementar interfaces.Structs do not support inheritance, but they can implement interfaces. Para obter mais informações, consulte Interfaces.For more information, see Interfaces.

Conceitualmente, uma classe derivada é uma especialização da classe base.Conceptually, a derived class is a specialization of the base class. Por exemplo, se tiver uma classe base Animal, você pode ter uma classe derivada chamada Mammal e outra classe derivada chamada 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. Um Mammal é um Animal e um Reptile é um Animal, mas cada classe derivada representa especializações diferentes da classe base.A Mammal is an Animal, and a Reptile is an Animal, but each derived class represents different specializations of the base class.

Quando você define uma classe para derivar de outra classe, a classe derivada obtém implicitamente todos os membros da classe base, exceto por seus construtores e finalizadores.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. A classe derivada pode, assim, reutilizar o código na classe base sem precisar implementá-lo novamente.The derived class can thereby reuse the code in the base class without having to re-implement it. Na classe derivada, você pode adicionar mais membros.In the derived class, you can add more members. Dessa forma, a classe derivada estende a funcionalidade da classe base.In this manner, the derived class extends the functionality of the base class.

A ilustração a seguir mostra uma classe WorkItem que representa um item de trabalho em um processo comercial.The following illustration shows a class WorkItem that represents an item of work in some business process. Como todas as classes, ela deriva de System.Object e herda todos os seus métodos.Like all classes, it derives from System.Object and inherits all its methods. WorkItem adiciona cinco membros próprios.WorkItem adds five members of its own. Eles incluem um construtor, porque os construtores não são herdados.These include a constructor, because constructors are not inherited. A classe ChangeRequest herda de WorkItem e representa um tipo específico de item de trabalho.Class ChangeRequest inherits from WorkItem and represents a particular kind of work item. ChangeRequest adiciona mais dois membros aos membros que herda de WorkItem e de Object.ChangeRequest adds two more members to the members that it inherits from WorkItem and from Object. Ele deve adicionar seu próprio construtor e também adiciona originalItemID.It must add its own constructor, and it also adds originalItemID. A propriedade originalItemID permite que a instância ChangeRequest seja associada ao WorkItem original a que a solicitação de alteração se aplica.Property originalItemID enables the ChangeRequest instance to be associated with the original WorkItem to which the change request applies.

Diagrama que mostra a herança de classe

O exemplo a seguir mostra como as relações entre as classes demonstradas na ilustração anterior são expressos em C#.The following example shows how the class relationships demonstrated in the previous illustration are expressed in C#. O exemplo também mostra como WorkItem substitui o método virtual Object.ToString e como a classe ChangeRequest herda a implementação de WorkItem do método.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
*/

Métodos abstratos e virtuaisAbstract and Virtual Methods

Quando uma classe base declara um método como virtual, uma classe derivada pode substituir o método por sua própria implementação.When a base class declares a method as virtual, a derived class can override the method with its own implementation. Se uma classe base declarar um membro como abstrato, esse método deve ser substituído em qualquer classe não abstrata que herdar diretamente da 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. Se uma classe derivada for abstrato, ele herdará membros abstratos sem implementá-los.If a derived class is itself abstract, it inherits abstract members without implementing them. Membros abstratos e virtuais são a base do polimorfismo, que é a segunda característica principal da programação orientada a objetos.Abstract and virtual members are the basis for polymorphism, which is the second primary characteristic of object-oriented programming. Para obter mais informações, consulte Polimorfismo.For more information, see Polymorphism.

Classes base abstratasAbstract Base Classes

Você pode declarar uma classe como abstrata se quiser impedir a instanciação direta usando a palavra-chave new.You can declare a class as abstract if you want to prevent direct instantiation by using the new keyword. Se você fizer isso, a classe poderá ser usada somente se uma nova classe for derivada dela.If you do this, the class can be used only if a new class is derived from it. Uma classe abstrata pode conter uma ou mais assinaturas de método que também são declaradas como abstratas.An abstract class can contain one or more method signatures that themselves are declared as abstract. Essas assinaturas especificam os parâmetros e o valor retornado, mas não têm nenhuma implementação (corpo do método).These signatures specify the parameters and return value but have no implementation (method body). Uma classe abstrata não precisa conter membros abstratos. No entanto, se uma classe contiver um membro abstrato, a própria classe deverá ser declarada como abstrata.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. Classes derivadas que não são abstratas devem fornecer a implementação para qualquer método abstrato de uma classe base abstrata.Derived classes that are not abstract themselves must provide the implementation for any abstract methods from an abstract base class. Para obter mais informações, consulte Classes e Membros de Classes Abstratos e Lacrados.For more information, see Abstract and Sealed Classes and Class Members.

InterfacesInterfaces

Uma interface é um tipo de referência semelhante a uma classe base abstrata que consiste somente em membros abstratos.An interface is a reference type that is somewhat similar to an abstract base class that consists of only abstract members. Quando uma classe implementa uma interface, ela deve fornecer uma implementação para todos os membros da interface.When a class implements an interface, it must provide an implementation for all the members of the interface. Uma classe pode implementar várias interfaces, mesmo que ela possa derivar de apenas uma classe base direta.A class can implement multiple interfaces even though it can derive from only a single direct base class.

Interfaces são usadas para definir recursos específicos para classes que não têm necessariamente uma relação do tipo “é um".Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. Por exemplo, a interface System.IEquatable<T> pode ser implementada por qualquer classe ou struct que precise habilitar o código do cliente para determinar se dois objetos do tipo são equivalentes (como quer que o tipo defina a equivalência).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> não implica o mesmo tipo de relação "é um" existente entre uma classe base e uma classe derivada (por exemplo, um Mammal é um 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). Para obter mais informações, consulte Interfaces.For more information, see Interfaces.

Impedindo derivações adicionaisPreventing Further Derivation

Uma classe pode impedir que outras classes herdem dela ou de qualquer um de seus membros, declarando a si mesmo ou o membro como lacrado.A class can prevent other classes from inheriting from it, or from any of its members, by declaring itself or the member as sealed. Para obter mais informações, consulte Classes e Membros de Classes Abstratos e Lacrados.For more information, see Abstract and Sealed Classes and Class Members.

Ocultação de membros da classe base pela classe derivadaDerived Class Hiding of Base Class Members

Uma classe derivada pode ocultar membros da classe base declarando membros com mesmo nome e assinatura.A derived class can hide base class members by declaring members with the same name and signature. O modificador new pode ser usado para indicar explicitamente que o membro não pretende ser uma substituição do membro base.The new modifier can be used to explicitly indicate that the member is not intended to be an override of the base member. O uso de new não é obrigatório, mas um aviso do compilador será gerado se new não for usado.The use of new is not required, but a compiler warning will be generated if new is not used. Para obter mais informações, consulte Controle de versão com as palavras-chave override e new e Quando usar as palavras-chave override e new.For more information, see Versioning with the Override and New Keywords and Knowing When to Use Override and New Keywords.

Consulte tambémSee also