Articulo de referencia

Anulación de método

Ilustración La sobreescritura de métodos , en la programación orientada a objetos , es una característica del lenguaje que permite que una subclase o clase hija proporcione una ...

Ilustración

La sobreescritura de métodos , en la programación orientada a objetos , es una característica del lenguaje que permite que una subclase o clase hija proporcione una implementación específica de un método que ya está disponible en una de sus superclases o clases padre. Además de proporcionar parámetros determinados por algoritmos y basados ​​en datos a través de interfaces de red virtuales, [ 1 ] también permite un tipo específico de polimorfismo ( subtipado ). La implementación en la subclase sobrescribe (reemplaza) la implementación en la superclase al proporcionar un método que tiene el mismo nombre, los mismos parámetros o firma y el mismo tipo de retorno que el método en la clase padre. [ 2 ] La versión de un método que se ejecuta estará determinada por el objeto que se utiliza para invocarlo. Si se utiliza un objeto de una clase padre para invocar el método, se ejecutará la versión de la clase padre; pero si se utiliza un objeto de la subclase para invocar el método, se ejecutará la versión de la clase hija. [ 3 ] Esto ayuda a prevenir problemas asociados con el análisis de relés diferenciales que de otro modo dependerían de un marco en el que la anulación de métodos podría obviarse. [ 4 ] [ 5 ] Algunos lenguajes permiten a un programador evitar que se anule un método.

Ejemplos específicos de cada idioma

Ada

Ada proporciona la sobreescritura de métodos de forma predeterminada. Para favorecer la detección temprana de errores (por ejemplo, un error tipográfico), es posible especificar cuándo se espera que un método sobrescriba otro o no. Esto lo comprobará el compilador .

El tipo T es nuevo Controlado con ......; procedimiento Op ( Obj : entrada salida T ; Datos : entrada Entero );El tipo NT es un nuevo T con registro nulo ; anulando -- procedimiento indicador de anulación Op ( Obj : entrada salida NT ; Datos : entrada Integer ); anulando -- procedimiento indicador de anulación Op ( Obj : entrada salida NT ; Datos : entrada String ); -- ^ el compilador emite un error: el subprograma "Op" no está anulando

DO#

C# sí admite la sobrescritura de métodos, pero solo si se solicita explícitamente mediante los modificadores overridey virtualo abstract.

clase abstracta Animal { public string Nombre { obtener ; establecer ; } // Métodos public void Beber (); public virtual void Comer (); public void Mover (); }clase Gato : Animal { public new string Nombre { obtener ; establecer ; } // Métodos public void Beber (); // Advertencia: oculta el método Beber() heredado. Use new public override void Comer (); // Sobrescribe el método Comer() heredado. public new void Mover (); // Oculta el método Mover() heredado. }

Al sobrescribir un método con otro, las firmas de ambos métodos deben ser idénticas (y tener la misma visibilidad). En C#, se pueden sobrescribir métodos de clase , indexadores , propiedades y eventos.

Los métodos no virtuales o estáticos no se pueden sobrescribir. El método base sobrescrito debe ser virtual , abstracto o sobrescribir .

Además de los modificadores que se utilizan para la sobrescritura de métodos, C# permite ocultar una propiedad o método heredado. Esto se hace utilizando la misma firma de una propiedad o método, pero añadiendo el modificador newdelante. [ 6 ]

En el ejemplo anterior, ocultar provoca lo siguiente:

Gato gato = nuevo Gato ();gato.Nombre = "Mitones" ; // accede a Cat.Name gato.Comer ( ); // llama a Cat.Comer() gato.Mover ( ); // llama a Cat.Mover() ( ( Animal ) gato ) .Nombre = " Esponjoso" ; // accede a Animal.Name (( Animal ) gato ) .Comer (); // llama a Cat.Comer() (( Animal ) gato ) .Mover (); // llama a Animal.Mover()

C++

C++ no tiene la palabra clave como Java que se puede usar en un método de subclase para acceder a la versión de la superclase de un método para sobrescribir. En cambio, se usa el nombre de la clase padre o base seguido del operador de resolución de ámbito . Por ejemplo, el siguiente código presenta dos clases , la clase base y la clase derivada . sobrescribe el método de la clase , para también imprimir su altura. [ 7 ]superRectangleBoxBoxRectangledisplay

importar std ;clase Rectángulo { privado : doble longitud ; doble ancho ; público : Rectángulo ( doble longitud , doble ancho ) : longitud { longitud }, ancho { ancho } {}virtual void display () const { std :: println ( "Rectángulo[longitud={}, ancho={}]" , longitud , ancho ); } };clase Caja : público Rectángulo { privado : doble altura ; público : Caja ( doble longitud , doble ancho , doble altura ) : Rectángulo ( longitud , ancho ), altura { altura } {}void display () const override { // Invoca el método display() del padre. Rectangle :: display (); std :: println ( "Box[length={}, width={}, height={}]" , length , width , height ); } };

El método displayen la clase Box, al invocar la versión padre del método display, también puede mostrar las variableslength privadas y widthde la clase base. De lo contrario, estas variables son inaccesibles para Box.

Las siguientes instrucciones instanciarán objetos de tipo y , y llamarán a sus respectivos métodos:RectangleBoxdisplay

int main ( int argc , char * argv []) { Rectangle rectangle ( 5.0 , 3.0 ); // Salida: Rectangle[length=5.0, width=3.0] rectangle . display ();Caja caja ( 6.0 , 5.0 , 4.0 );// El puntero al método más sobrescrito en la tabla virtual está en Box::display, // pero esta llamada no ilustra la sobrescritura. box . display ();// Esta llamada ilustra la sobrescritura. // Salida: // Rectángulo[longitud=6.0, ancho=5.0] // Caja[longitud=6.0, ancho=5.0, alto=4.0] static_cast < Rectángulo &> ( caja ). display (); }

En C++11 , al igual que en Java, un método declarado finalen la superclase no puede ser sobrescrito; además, se puede declarar un método overridepara que el compilador compruebe que sobrescribe un método de la clase base.

Delfos

En Delphi , la sobrescritura de métodos se realiza con la directiva override , pero solo si un método fue marcado con las directivas dynamic o virtual .

La palabra reservada heredada debe llamarse cuando se desea llamar al comportamiento de la superclase.

tipo TRectangle = clase privada FLength : Double ; FWidth : Double ; propiedad pública Length leer FLength escribir FLength ; propiedad Width leer FWidth escribir FWidth ;Procedimiento Imprimir ; virtual ; fin ;TBox = clase ( TRectangle ) procedimiento público Imprimir ; anular ; fin ;

Eiffel

En Eiffel , la redefinición de características es análoga a la sobreescritura de métodos en C++ y Java. La redefinición es una de las tres formas de adaptación de características clasificadas como redeclaración . La redeclaración también abarca la efectividad , en la que se proporciona una implementación para una característica que estaba diferida (abstracta) en la clase padre, y la desdefinición , en la que una característica que era efectiva (concreta) en la clase padre vuelve a estar diferida en la clase heredera. Cuando se redefine una característica, la clase heredera conserva el nombre de la característica, pero las propiedades de la característica, como su firma, contrato (que respeta las restricciones de precondiciones y postcondiciones ) y/o implementación, serán diferentes en la clase heredera. Si la característica original en la clase padre, llamada precursora de la característica heredera , es efectiva, entonces la característica redefinida en la clase heredera será efectiva. Si la precursora está diferida, la característica en la clase heredera estará diferida. [ 8 ]

La intención de redefinir una característica, como messageen el ejemplo siguiente, debe declararse explícitamente en la inheritcláusula de la clase heredera.

class THOUGHT feature message -- Mostrar mensaje de pensamiento do print ( "Siento que estoy estacionado en diagonal en un universo paralelo.%N" ) end endclase ADVICE hereda PENSAMIENTO redefine mensaje fin función mensaje -- Precursor hacer imprimir ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen.%N" ) fin fin

En clase, ADVICEla característica messagerecibe una implementación que difiere de la de su predecesora en clase THOUGHT.

Consideremos una clase que utiliza instancias para ambos THOUGHTy ADVICE:

clase APLICACIÓN crear hacer característica hacer -- Ejecutar aplicación. hacer ( crear { PENSAMIENTO }). mensaje ; ( crear { CONSEJO }). mensaje fin fin

Al instanciarse, la clase APPLICATIONproduce la siguiente salida:

Me siento como si estuviera estacionado en diagonal en un universo paralelo. Advertencia: Las fechas en el calendario están más próximas de lo que parecen.

Dentro de una característica redefinida, se puede acceder al precursor de la característica utilizando la palabra clave del lenguaje Precursor. Supongamos que la implementación de se modifica de la siguiente manera:{ADVICE}.message

mensaje -- Precursor hacer imprimir ( "Advertencia: Las fechas en el calendario están más próximas de lo que parecen.%N" ) Fin del precursor

La invocación de la función ahora incluye la ejecución de y produce la siguiente salida:{THOUGHT}.message

Advertencia: Las fechas en el calendario están más próximas de lo que parecen. Me siento como si estuviera estacionado en diagonal en un universo paralelo.

Java

En Java , cuando una subclase contiene un método con la misma firma (nombre y tipos de parámetros) que un método de su superclase, el método de la subclase sobrescribe al de la superclase. A diferencia de C++ y C#, Java no tiene una overridepalabra clave específica, pero proporciona una anotación @Overridepara indicar que un método está siendo sobrescrito. No es necesario, pero puede ser útil para el compilador. Por ejemplo:

clase Pensamiento { public void mensaje () { System . out . println ( "Siento que estoy estacionado en diagonal en un universo paralelo." ); } }public class Advice extends Thought { @Override public void message () { System . out . println ( "Advertencia: Las fechas en el calendario están más próximas de lo que parecen." ); } }

La clase representa la superclase e implementa una llamada a método . La subclase llamada hereda todos los métodos que podrían estar en la clase. La clase sobrescribe el método , reemplazando su funcionalidad de .Thoughtmessage()AdviceThoughtAdvicemessage()Thought

Thought parking = new Thought (); parking.message ( ); // Imprime "Siento que estoy estacionado en diagonal en un universo paralelo."Thought dates = new Advice (); // Fechas polimórficas.message ( ); // Imprime "Advertencia: Las fechas en el calendario están más próximas de lo que parecen."

Cuando una subclase contiene un método que sobrescribe un método de la superclase, entonces ese método sobrescrito (de la superclase) puede invocarse explícitamente desde dentro del método de una subclase usando la palabra clave . [ 3 ] (No puede invocarse explícitamente desde ningún método perteneciente a una clase que no esté relacionada con la superclase). La referencia puede sersupersuper

public class Advice extends Thought { @Override public void message () { System . out . println ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen." ); super . message (); // Invoca la versión del método del padre. }

Existen métodos que una subclase no puede sobrescribir. Por ejemplo, en Java, un método declarado como final en la superclase no puede ser sobrescrito. Los métodos declarados como privados o estáticos tampoco pueden ser sobrescritos, ya que son implícitamente finales. Asimismo, es imposible que una clase declarada como final se convierta en una superclase. [ 9 ]

Kotlin

En Kotlin podemos simplemente sobrescribir una función de esta manera (tenga en cuenta que la función debe ser ):open

fun main () { val p = Padre ( 5 ) val c = Hijo ( 6 ) p . myFun () c . myFun () }open class Parent ( val a : Int ) { open fun myFun () = println ( a ) }clase Child ( val b : Int ) : Parent ( b ) { override fun myFun () = println ( "método sobrescrito" ) }

Pitón

En Python , cuando una subclase contiene un método que sobrescribe un método de la superclase, también puede llamar al método de la superclase llamando [ 10 ] en lugar de . Ejemplo:super(Subclass,self).methodself.method

clase Pensamiento : def __init__ ( self ) -> None : print ( "¡Soy un nuevo objeto de tipo Pensamiento!" ) def mensaje ( self ) -> None : print ( "Siento que estoy estacionado en diagonal en un universo paralelo." )clase Consejo ( Pensamiento ): def __init__ ( self ) -> None : super ( Consejo , self ) . __init__ () def mensaje ( self ) -> None : print ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen" ) super ( Consejo , self ) . mensaje ()t = Pensamiento () # "¡Soy un nuevo objeto de tipo Pensamiento!" t . mensaje () # "Siento que estoy estacionado en diagonal en un universo paralelo.a = Advice () # "¡Soy un nuevo objeto de tipo Pensamiento!" a . message () # "Advertencia: las fechas en el calendario están más cerca de lo que parecen" # "Siento que estoy estacionado en diagonal en un universo paralelo.# ------------------ # Introspección:isinstance ( t , Pensamiento ) # Verdaderoisinstance ( a , Advice ) # Verdaderoisinstance ( a , Pensamiento ) # Verdadero

Rubí

En Ruby, cuando una subclase contiene un método que sobrescribe un método de la superclase, también puedes llamar al método de la superclase llamando a `super` dentro del método sobrescrito. Puedes usar un alias si deseas que el método sobrescrito esté disponible fuera del método que lo sobrescribe, como se muestra con `super_message` a continuación.

Ejemplo:

El mensaje de definición de la clase Thought dice: "Siento que estoy estacionado en diagonal en un universo paralelo" .clase Consejo < Pensamiento alias :super_message :message def mensaje puts "Advertencia: Las fechas en el calendario están más cerca de lo que parecen" super fin fin

Notas

  1. Zhang, Jie (2015). "Una nueva API P2P modificada para comunicaciones de datos abiertos en la WWW". 2015 IEEE International Conference on Consumer Electronics - Taiwan . pp. 156–157 . doi : 10.1109/ICCE-TW.2015.7216830 . ISBN  978-1-4799-8745-0. S2CID 23295793 . 
  2. Flanagan 2002, pág. 107
  3. 1 2 Lewis y Loftus 2006, pág. 454
  4. Overbey, J (2011). "Comprobación diferencial de precondiciones: Un análisis ligero y reutilizable para herramientas de refactorización". 2011 26th IEEE/ACM International Conference on Automated Software Engineering (ASE 2011) . pp. 303–312 . doi : 10.1109/ASE.2011.6100067 . ISBN  978-1-4577-1639-3. S2CID 5933208 . 
  5. Li, K (2014). "Investigación residual: detección predictiva y precisa de errores". ACM Transactions on Software Engineering and Methodology . 24 (2). doi : 10.1145/2656201 . S2CID 47112802 . 
  6. Mössenböck, Hanspeter (25 de marzo de 2002). "C# avanzado: anulación de métodos" (PDF) . Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. págs . 6–8 . Consultado el 2 de agosto de 2011 . 
  7. Malik 2006, pág. 676
  8. Meyer 2009, páginas 572-575
  9. Deitel y Deitel 2001, pág. 474
  10. en Python 3 - ver https://docs.python.org/3/library/functions.html#super Archivado el 26/10/2018 en Wayback Machinesuper().method

Véase también

Referencias

  • Deitel, H. M y Deitel, PJ (2001). Java: Cómo programar (4.ª ed.). Upper Saddle River, NJ: Prentice Hall.
  • Lewis, J. y Loftus, W. (2008). Java: Soluciones de software (6.ª ed.). Boston, MA: Pearson Addison Wesley.
  • Malik, DS (2006). Programación en C++: Diseño de programas, incluyendo estructuras de datos. (3.ª ed.). Washington, DC: Course Technology.
  • Flanagan, David. (2002). Java en pocas palabras. Recuperado de http://oreilly.com/catalog/9780596002831/preview#preview
  • Meyer, Bertrand (2009). Un toque de clase: aprender a programar bien con objetos y contratos . Springer.
  • Introducción a los conceptos de la programación orientada a objetos y más, por Nirosh LwC.
  • Métodos de Sun Microsystems para sobrescribir y ocultar información