Fundamentos de la herencia (Visual Basic)
La instrucción Inherits
se usa para declarar una nueva clase, denominada clase derivada, basada en una clase existente, conocida como clase base. Las clases derivadas heredan y pueden extenderse, las propiedades, métodos, eventos, campos y constantes definidos en la clase base. En la siguiente sección se describen algunas de las reglas de herencia y los modificadores que se pueden usar para cambiar la forma en que las clases heredan o se heredan:
De forma predeterminada, todas las clases se pueden heredar a menos que se marquen con la palabra clave
NotInheritable
. Las clases pueden heredar de otras clases del proyecto o de clases de otros ensamblados a los que hace referencia el proyecto.A diferencia de los lenguajes que permiten la herencia múltiple, Visual Basic solo permite la herencia única en clases; es decir, las clases derivadas solo pueden tener una clase base. Aunque no se permite la herencia múltiple en clases, las clases pueden implementar varias interfaces, lo que puede lograr eficazmente los mismos extremos.
Para evitar exponer elementos restringidos en una clase base, el tipo de acceso de una clase derivada debe ser igual o más restrictivo que su clase base. Por ejemplo, una clase
Public
no puede heredar una claseFriend
oPrivate
, y una claseFriend
no puede heredar una clasePrivate
.
Modificadores de herencia
Visual Basic presenta las siguientes instrucciones y modificadores de nivel de clase para admitir la herencia:
Instrucción
Inherits
: especifica la clase base.Modificador
NotInheritable
: impide que los programadores usen la clase como una clase base.Modificador
MustInherit
: especifica que la clase está pensada para usarse solo como clase base. Las instancias de clasesMustInherit
no se pueden crear directamente; solo se pueden crear como instancias de clase base de una clase derivada. (Otros lenguajes de programación, como C++ y C#, use el término clase abstracta para describir dicha clase).
Invalidación de propiedades y métodos en clases derivadas
De forma predeterminada, una clase derivada hereda todas las propiedades y métodos de su clase base. Si una propiedad o método heredados tiene que comportarse de forma diferente en la clase derivada, se puede invalidar. Es decir, se puede definir una nueva implementación del método en la clase derivada. Los siguientes modificadores se utilizan para controlar cómo se reemplazan propiedades y métodos:
Overridable
permite que una propiedad o un método de una clase se invalide en una clase derivada.Overrides
invalida una propiedad o métodoOverridable
definido en la clase base.NotOverridable
impide que una propiedad o método se invalide en una clase heredada. De forma predeterminada, los métodosPublic
sonNotOverridable
.MustOverride
requiere que una clase derivada invalide la propiedad o el método. Cuando se usa la palabra claveMustOverride
, la definición del método consta solo de la instrucciónSub
,Function
oProperty
. No se permiten otras instrucciones y, en concreto, no hay ninguna instrucciónEnd Sub
oEnd Function
. Los métodosMustOverride
deben declararse en clasesMustInherit
.
Supongamos que quiere definir clases para controlar las nóminas. Puede definir una clase genérica Payroll
que contenga un método RunPayroll
que calcule la nómina de una semana típica. Después, podría usar Payroll
como clase base para una clase más especializada BonusPayroll
, que se podría usar al distribuir bonificaciones de empleados.
La clase BonusPayroll
puede heredar e invalidar el método PayEmployee
definido en la clase base Payroll
.
En el ejemplo siguiente se define una clase base, Payroll
, y una clase derivada, , BonusPayroll
que invalida un método heredado, PayEmployee
. Un procedimiento, RunPayroll
, crea y, a continuación, pasa un objeto Payroll
y un objeto BonusPayroll
a una función, Pay
, que ejecuta el método PayEmployee
de ambos objetos.
Const BonusRate As Decimal = 1.45D
Const PayRate As Decimal = 14.75D
Class Payroll
Overridable Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
PayEmployee = HoursWorked * PayRate
End Function
End Class
Class BonusPayroll
Inherits Payroll
Overrides Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
' The following code calls the original method in the base
' class, and then modifies the returned value.
PayEmployee = MyBase.PayEmployee(HoursWorked, PayRate) * BonusRate
End Function
End Class
Sub RunPayroll()
Dim PayrollItem As Payroll = New Payroll
Dim BonusPayrollItem As New BonusPayroll
Dim HoursWorked As Decimal = 40
MsgBox("Normal pay is: " &
PayrollItem.PayEmployee(HoursWorked, PayRate))
MsgBox("Pay with bonus is: " &
BonusPayrollItem.PayEmployee(HoursWorked, PayRate))
End Sub
La Palabra clave MyBase
La palabra clave MyBase
se comporta como una variable de objeto que hace referencia a la clase base de la instancia actual de una clase. MyBase
se usa normalmente para acceder a los miembros de la clase base que se invalidan o se reemplazan en una clase derivada. En concreto, MyBase.New
se usa para llamar explícitamente a un constructor de clase base desde un constructor de clase derivada.
Por ejemplo, supongamos que está diseñando una clase derivada que invalida un método heredado de la clase base. El método invalidado puede llamar al método en la clase base y modificar el valor devuelto, como se muestra en el siguiente fragmento de código:
Class DerivedClass
Inherits BaseClass
Public Overrides Function CalculateShipping(
ByVal Dist As Double,
ByVal Rate As Double) As Double
' Call the method in the base class and modify the return value.
Return MyBase.CalculateShipping(Dist, Rate) * 2
End Function
End Class
En la siguiente lista se describen las restricciones en el uso de MyBase
:
MyBase
hace referencia a la clase base inmediata y a sus miembros heredados. No se puede usar para tener acceso a los miembrosPrivate
de la clase.MyBase
es una palabra clave, no un objeto real.MyBase
no se puede asignar a una variable, pasar a procedimientos o usarse en una comparaciónIs
.El método que califica
MyBase
no tiene que definirse en la clase base inmediata; en su lugar, se puede definir en una clase base heredada indirectamente. Para que una referencia calificada porMyBase
se compile correctamente, algunas clases base deben contener un método que coincida con el nombre y los tipos de parámetros que aparecen en la llamada.No se puede usar
MyBase
para llamar a métodos de clase baseMustOverride
.MyBase
no se puede usar para calificarse a sí mismo. Por consiguiente, el siguiente código no es válido:MyBase.MyBase.BtnOK_Click()
MyBase
no se puede usar en módulos.MyBase
no se puede usar para tener acceso a los miembros de clase base marcados comoFriend
si la clase base se encuentra en un ensamblado diferente.
Para obtener más información y otro ejemplo, consulte Obtener acceso a una variable oculta por una clase derivada.
La palabra clave MyClass
La palabra clave MyClass
se comporta como una variable de objeto que hace referencia a la instancia actual de una clase según su implementación original. MyClass
es similar a Me
, pero todas las llamadas a métodos y propiedades de MyClass
se tratan como si el método o la propiedad fueran NotOverridable. Por lo tanto, el método o la propiedad no se ven afectados por la invalidación en una clase derivada.
MyClass
es una palabra clave, no un objeto real.MyClass
no se puede asignar a una variable, pasar a procedimientos o usarse en una comparaciónIs
.MyClass
hace referencia a la clase contenedora y a sus miembros heredados.MyClass
se puede usar como calificador para los miembrosShared
.MyClass
no se puede usar dentro de un métodoShared
, pero se puede usar dentro de un método de instancia para tener acceso a un miembro compartido de una clase.MyClass
no se puede usar en módulos estándar.MyClass
se puede usar para calificar un método definido en una clase base y que no tiene ninguna implementación del método proporcionado en esa clase. Esta referencia tiene el mismo significado que MétodoMyBase.
.
El siguiente ejemplo compara Me
y MyClass
.
Class baseClass
Public Overridable Sub testMethod()
MsgBox("Base class string")
End Sub
Public Sub useMe()
' The following call uses the calling class's method, even if
' that method is an override.
Me.testMethod()
End Sub
Public Sub useMyClass()
' The following call uses this instance's method and not any
' override.
MyClass.testMethod()
End Sub
End Class
Class derivedClass : Inherits baseClass
Public Overrides Sub testMethod()
MsgBox("Derived class string")
End Sub
End Class
Class testClasses
Sub startHere()
Dim testObj As derivedClass = New derivedClass()
' The following call displays "Derived class string".
testObj.useMe()
' The following call displays "Base class string".
testObj.useMyClass()
End Sub
End Class
Aunque derivedClass
invalida testMethod
, la palabra clave MyClass
en useMyClass
anula los efectos de invalidación y el compilador resuelve la llamada a la versión de clase base de testMethod
.