Herencia (Guía de programación de C#)Inheritance (C# Programming Guide)

La herencia, junto con la encapsulación y el polimorfismo, es una de las tres características principales de la programación orientada a objetos.Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. La herencia permite crear clases nuevas que reutilizan, extienden y modifican el comportamiento que se define en otras clases.Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. La clase cuyos miembros se heredan se denomina clase base y la clase que hereda esos miembros se denomina clase derivada.The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. Una clase derivada solo puede tener una clase base directa,A derived class can have only one direct base class. pero la herencia es transitiva.However, inheritance is transitive. Si ClaseC se deriva de ClaseB y ClaseB se deriva de ClaseA, ClaseC hereda los miembros declarados en ClaseB y ClaseA.If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Nota

Los structs no admiten la herencia, pero pueden implementar interfaces.Structs do not support inheritance, but they can implement interfaces. Para más información, vea Interfaces.For more information, see Interfaces.

Conceptualmente, una clase derivada es una especialización de la clase base.Conceptually, a derived class is a specialization of the base class. Por ejemplo, si tiene una clase base Animal, podría tener una clase derivada denominada Mammal y otra clase derivada denominada 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. Mammal es Animal y Reptile también es Animal, pero cada clase derivada representa especializaciones diferentes de la clase base.A Mammal is an Animal, and a Reptile is an Animal, but each derived class represents different specializations of the base class.

Cuando se define una clase para que derive de otra clase, la clase derivada obtiene implícitamente todos los miembros de la clase base, salvo sus constructores y sus 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. La clase derivada puede reutilizar el código de la clase base sin tener que volver a implementarlo.The derived class can thereby reuse the code in the base class without having to re-implement it. Puede agregar más miembros en la clase derivada.In the derived class, you can add more members. De esta manera, la clase derivada amplía la funcionalidad de la clase base.In this manner, the derived class extends the functionality of the base class.

En la ilustración siguiente se muestra una clase WorkItem que representa un elemento de trabajo de un proceso empresarial.The following illustration shows a class WorkItem that represents an item of work in some business process. Como con todas las clases, se deriva de System.Object y hereda todos sus métodos.Like all classes, it derives from System.Object and inherits all its methods. WorkItem agrega cinco miembros propios.WorkItem adds five members of its own. Entre estos se incluye un constructor, dado que los constructores no se heredan.These include a constructor, because constructors are not inherited. La clase ChangeRequest hereda de WorkItem y representa un tipo concreto de elemento de trabajo.Class ChangeRequest inherits from WorkItem and represents a particular kind of work item. ChangeRequest agrega dos miembros más a los miembros que hereda de WorkItem y de Object.ChangeRequest adds two more members to the members that it inherits from WorkItem and from Object. Debe agregar su propio constructor y además agrega originalItemID.It must add its own constructor, and it also adds originalItemID. La propiedad originalItemID permite que la instancia ChangeRequest se asocie con el WorkItem original al que se aplica la solicitud de cambio.Property originalItemID enables the ChangeRequest instance to be associated with the original WorkItem to which the change request applies.

Herencia de clasesClass Inheritance
Herencia de clasesClass inheritance

En el ejemplo siguiente se muestra cómo se expresan en C# las relaciones de clase de la ilustración anterior.The following example shows how the class relationships demonstrated in the previous illustration are expressed in C#. En el ejemplo también se muestra cómo WorkItem reemplaza el método virtual Object.ToString y cómo la clase ChangeRequest hereda la implementación WorkItem del 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 String.Format("{0} - {1}", 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 abstractos y virtualesAbstract and Virtual Methods

Cuando una clase base declara un método como virtual, una clase derivada puede reemplazar el método con su propia implementación.When a base class declares a method as virtual, a derived class can override the method with its own implementation. Si una clase base declara un miembro como abstracto, ese método se debe reemplazar en todas las clases no abstractas que hereden directamente de dicha clase.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. Si una clase derivada es abstracta, hereda los miembros abstractos sin implementarlos.If a derived class is itself abstract, it inherits abstract members without implementing them. Los miembros abstractos y virtuales son la base del polimorfismo, que es la segunda característica principal de la programación orientada a objetos.Abstract and virtual members are the basis for polymorphism, which is the second primary characteristic of object-oriented programming. Para obtener más información, vea Polimorfismo .For more information, see Polymorphism.

Clases base abstractasAbstract Base Classes

Puede declarar una clase como abstracta para quiere impedir la creación directa de instancias mediante la palabra clave new.You can declare a class as abstract if you want to prevent direct instantiation by using the new keyword. Si lo hace, la clase solo se puede usar si se deriva de ella una clase nueva.If you do this, the class can be used only if a new class is derived from it. Una clase abstracta puede contener una o más firmas de método que, a su vez, se declaran como abstractas.An abstract class can contain one or more method signatures that themselves are declared as abstract. Estas firmas especifican los parámetros y el valor devuelto, pero no tienen ninguna implementación (cuerpo del método).These signatures specify the parameters and return value but have no implementation (method body). Una clase abstracta no tiene que contener miembros abstractos, pero si lo hace, la clase debe declararse como abstracta.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. Las clases derivadas que no son abstractas deben proporcionar la implementación para todos los métodos abstractos de una clase base abstracta.Derived classes that are not abstract themselves must provide the implementation for any abstract methods from an abstract base class. Para más información, vea Clases y miembros de clase abstractos y sellados.For more information, see Abstract and Sealed Classes and Class Members.

InterfacesInterfaces

Una interfaz es un tipo de referencia similar a una clase base abstracta formada únicamente por miembros abstractos.An interface is a reference type that is somewhat similar to an abstract base class that consists of only abstract members. Cuando una clase implementa una interfaz, debe proporcionar una implementación para todos los miembros de la interfaz.When a class implements an interface, it must provide an implementation for all the members of the interface. Una clase puede implementar varias interfaces, aunque solo puede derivar de una única clase base directa.A class can implement multiple interfaces even though it can derive from only a single direct base class.

Las interfaces se usan para definir funciones específicas para clases que no tienen necesariamente una relación "es un/una".Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. Por ejemplo, la interfaz System.IEquatable<T> se puede implementar mediante cualquier clase o struct que deba permitir que el código de cliente determine si dos objetos del tipo son equivalentes (pero el tipo define la equivalencia).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> no implica el mismo tipo de relación "es un/una" que existe entre una clase base y una clase derivada (por ejemplo, Mammal es 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 más información, vea Interfaces.For more information, see Interfaces.

Impedir la derivación adicionalPreventing Further Derivation

Una clase puede impedir que otras clases hereden de ella o de cualquiera de sus miembros. Para ello, se declara a sí misma o declara su miembro como sellado.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 obtener más información, vea Clases y miembros de clase abstractos y sellados.For more information, see Abstract and Sealed Classes and Class Members.

Clase derivada que oculta miembros de clase baseDerived Class Hiding of Base Class Members

Una clase derivada puede ocultar miembros de clase base si declara los miembros con el mismo nombre y firma.A derived class can hide base class members by declaring members with the same name and signature. Se puede usar el modificador new para indicar explícitamente que el miembro no está diseñado para reemplazar al miembro base.The new modifier can be used to explicitly indicate that the member is not intended to be an override of the base member. No es necesario usar new, pero se generará una advertencia del compilador si no se usa new.The use of new is not required, but a compiler warning will be generated if new is not used. Para obtener más información, vea Control de versiones con las palabras clave Override y New y Saber cuándo usar las palabras clave Override y New.For more information, see Versioning with the Override and New Keywords and Knowing When to Use Override and New Keywords.

Vea tambiénSee Also