stringtranslate.com

Anulación de método

Ilustración

La anulación de métodos , en la programación orientada a objetos , es una característica del lenguaje que permite a una subclase o clase secundaria proporcionar una implementación específica de un método que ya proporciona una de sus superclases o clases principales. Además de proporcionar parámetros determinados por algoritmos basados ​​en datos en interfaces de red virtuales, [1] también permite un tipo específico de polimorfismo ( subtipificación ). La implementación en la subclase anula (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 principal. [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 principal para invocar el método, se ejecutará la versión en la clase principal, pero si se utiliza un objeto de la subclase para invocar el método, se ejecutará la versión en la clase secundaria. [3] Esto ayuda a prevenir problemas asociados con el análisis de relés diferenciales que, de lo contrario, dependerían de un marco en el que se podría obviar la anulación de métodos. [4] [5] Algunos lenguajes permiten a un programador evitar que se anule un método.

Ejemplos específicos del idioma

Ada

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

 el tipo  T  es  nuevo  Controlado  con  ......;  procedimiento  Op ( Obj : in  out  T ;  Dato : in  Integer ); tipo  NT  es  nuevo  T  con  registro nulo ;  anulación - anulando  el procedimiento indicador  Op ( Obj : in out NT ; Data : in Integer ); anulación - anulando el procedimiento indicador Op ( Obj : in out NT ; Data : in String ); - ^ el compilador emite un error: el subprograma "Op" no está anulando              

DO#

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

clase abstracta Animal { cadena pública Nombre { obtener ; establecer ; } // Métodos public void Beber (); public virtual void Comer (); public void Ir (); }                    clase Gato : Animal { public new string Nombre { get ; set ; } // Métodos public void Drink (); // Advertencia: oculta la función drink() heredada. Usar new public override void Eat (); // Reemplaza la función eat() heredada. public new void Go (); // Oculta la función go() heredada. }                          

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

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

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

En el ejemplo anterior, la ocultación provoca lo siguiente:

Gato gato = nuevo Gato ();    gato . Nombre = ​​; // accede a Gato.Nombre gato . Comer (); // llama a Gato.Comer() gato . Ir (); // llama a Gato.Ir() (( Animal ) gato ). Nombre = ​​; // accede a Animal.Nombre! (( Animal ) gato ). Comer (); // llama a Gato.Comer()! (( Animal ) gato ). Ir (); // llama a Animal.Ir()!          

C++

C++ no tiene la palabra clave superque una subclase puede usar en Java para invocar la versión de la superclase de un método que desea anular. En su lugar, se utiliza el nombre de la clase base o principal seguido del operador de resolución de alcance . Por ejemplo, el siguiente código presenta dos clases , la clase base Rectangley la clase derivada Box. Boxanula el método Rectanglede la clase Print, de modo que también imprime su altura. [7]

#include <flujo de datos> //--------------------------------------------------------------------------- clase Rectángulo { público : Rectángulo ( doble l , doble w ) : largo_ ( l ), ​​ancho_ ( w ) {} virtual void Imprimir () const ;                privado : doble largo_ ; doble ancho_ ; };    //--------------------------------------------------------------------------- void Rectangle::Print () const { // Método de impresión de la clase base. std :: cout << "Longitud = " << longitud_ << "; Ancho = " << ancho_ ; }             //--------------------------------------------------------------------------- clase Caja : public Rectangle { public : Caja ( double l , double w , double h ) : Rectangle ( l , w ), height_ ( h ) {} void Print () const override ;                      privado : doble altura_ ; };  //--------------------------------------------------------------------------- // Método de impresión de la clase derivada. void Box::Print () const { // Invocar el método padre Print. Rectangle :: Print (); std :: cout << "; Height = " << height_ ; }          

El método Printde la clase Box, al invocar la versión principal del método Print, también puede generar las variables length privadas y widthde la clase base. De lo contrario, estas variables no son accesibles para Box.

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

int main ( int argc , char ** argv ) { Rectángulo rectángulo ( 5.0 , 3.0 ) ;         // Salidas: Largo = 5.0; Ancho = 3.0 rectángulo . Imprimir ();  Caja caja ( 6.0 , 5.0 , 4.0 );    // El puntero al método más anulado en la vtable en Box::print, // pero esta llamada no ilustra la anulación. box . Print ();   // Esta llamada ilustra la anulación. // salidas: Longitud = 6.0; Ancho = 5.0; Alto = 4.0 static_cast < Rectangle &> ( box ). Print (); }  

En C++11 , de manera similar a Java, un método que se declara finalen la superclase no se puede anular; además, se puede declarar un método overridepara que el compilador verifique que anula un método en la clase base.

Delfos

En Delphi , la anulación de un método 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 ;       

Torre Eiffel

En Eiffel , la redefinición de características es análoga a la anulación 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 cubre la realización , en la que se proporciona una implementación para una característica que se aplazó (abstracta) en la clase padre, y la indefinición , en la que una característica que era efectiva (concreta) en la clase padre se aplaza nuevamente 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 (respetando las restricciones para las condiciones previas y posteriores ) y/o implementación, serán diferentes en la heredera. Si la característica original en la clase padre, llamada precursor de la característica heredera , es efectiva, entonces la característica redefinida en la heredera será efectiva. Si el precursor se aplaza, la característica en la heredera se aplazará. [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.

clase PENSAMIENTO característica mensaje -- Mostrar mensaje de pensamiento do print ( "Me siento como si estuviera estacionado en diagonal en un universo paralelo.%N" ) fin fin       clase CONSEJO heredar PENSAMIENTO redefinir mensaje fin característica mensaje -- Precursor hacer print ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen.%N" ) fin fin           

En la clase, ADVICEa la característica messagese le da una implementación que difiere de la de su precursora en la clase THOUGHT.

Considere una clase que utiliza instancias tanto para como THOUGHTpara ADVICE:

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

Cuando se crea una instancia, la clase APPLICATIONproduce el siguiente resultado:

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

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

 mensaje -- Precursor do print ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen.%N" ) Precursor end      

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

Advertencia: Las fechas en el calendario están más cerca 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 anula el de la superclase. Por ejemplo:

clase  Pensamiento { public void mensaje () { System . println ( " Me siento como si estuviera estacionado en diagonal en un universo paralelo." ); } }       public class Advice extiende Thought { @Override // La anotación @Override en Java 5 es opcional pero útil. public void message () { System . println ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen." ) ; } }             

La clase Thoughtrepresenta la superclase e implementa una llamada a un método . La subclase llamada hereda todos los métodos que podrían estar en la clase. La clase reemplaza el método y reemplaza su funcionalidad .message()AdviceThoughtAdvicemessage()Thought

Pensamiento estacionamiento = nuevo Pensamiento (); estacionamiento.mensaje (); // Imprime "Me siento como si estuviera estacionado en diagonal en un universo paralelo" .     Fechas de pensamiento = nuevo Consejo (); // Polimorfismo fechas.mensaje (); // Imprime "Advertencia : Las fechas en el calendario están más cerca de lo que parecen".      

Cuando una subclase contiene un método que anula un método de la superclase, entonces el método anulado de esa (superclase) se puede invocar explícitamente desde dentro del método de una subclase utilizando la palabra clave super . [3] (No se puede invocar explícitamente desde ningún método que pertenezca a una clase que no esté relacionada con la superclase). La superreferencia puede ser

clase pública Consejo extiende Pensamiento { @Override public void mensaje () { System . println ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen." ) ; super . message (); // Invocar la versión del método del padre. }              

Existen métodos que una subclase no puede anular. Por ejemplo, en Java, un método que se declara final en la superclase no se puede anular. Los métodos que se declaran privados o estáticos tampoco se pueden anular porque son implícitamente finales. También es imposible que una clase que se declara final se convierta en una superclase. [9]

Kotlin

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

diversión principal () { val p = Padre ( 5 ) val c = Hijo ( 6 ) p . myFun () c . myFun () }            abrir clase Padre ( val a : Int ) { abrir fun myFun () = println ( a ) }           clase Child ( val b : Int ) : Parent ( b ) { anular fun myFun () = println ( "método anulado" ) }            

Pitón

En Python , cuando una subclase contiene un método que reemplaza un método de la superclase, también puedes llamar al método de la superclase llamando a [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 ( "Me siento como si estuviera estacionado en diagonal en un universo paralelo." )clase  Advice ( Pensamiento ):  def  __init__ ( self )  ->  None :  super ( Advice ,  self ) .__ init__ ()  def  message ( self )  ->  None :  print ( "Advertencia: Las fechas en el calendario están más cerca de lo que parecen" )  super ( Advice ,  self ) .message ()t  =  Pensamiento () # "¡Soy un nuevo objeto de tipo Pensamiento!" t . mensaje () # "Me siento como si estuviera 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" # "Me siento como si estuviera estacionado en diagonal en un universo paralelo.# ------------------ # Introspección:isinstance ( t ,  Pensamiento ) # Verdaderoisinstance ( a ,  Consejo ) # Verdaderoisinstance ( a ,  Pensamiento ) # Verdadero

Rubí

En Ruby, cuando una subclase contiene un método que reemplaza a un método de la superclase, también puedes llamar al método de la superclase llamando a super en ese método reemplazado. Puedes usar alias si deseas mantener el método reemplazado disponible fuera del método reemplazado, como se muestra con 'super_message' a continuación.

Ejemplo:

clase Pensamiento def mensaje pone "Me siento como si estuviera estacionado en diagonal en un universo paralelo". fin fin      clase Advice < Thought alias :super_message :message def message puts "Advertencia: Las fechas en el calendario están más cerca de lo que parecen" super end end            

Notas

  1. ^ Zhang, Jie (2015). "Una nueva API reemplazada por P2P para comunicaciones de datos abiertos en la WWW". Conferencia internacional IEEE sobre electrónica de consumo de 2015 - Taiwán . págs. 156-157. doi :10.1109/ICCE-TW.2015.7216830. ISBN . 978-1-4799-8745-0.S2CID23295793  .​
  2. ^ Flanagan 2002, pág. 107
  3. ^ de Lewis y Loftus 2006, pág. 454
  4. ^ Overbey, J (2011). "Verificación diferencial de precondiciones: un análisis ligero y reutilizable para herramientas de refactorización". 26.ª Conferencia internacional IEEE/ACM sobre ingeniería de software automatizada (ASE 2011) de 2011. págs. 303–312. doi :10.1109/ASE.2011.6100067. ISBN 978-1-4577-1639-3. Número de identificación del sujeto  5933208.
  5. ^ Li, K (2014). "Investigación residual: detección de errores predictiva y precisa". 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ágina 572-575
  9. ^ Deitel y Deitel 2001, pág. 474
  10. ^ en Python 3 - consulte https://docs.python.org/3/library/functions.html#super Archivado el 26 de octubre de 2018 en Wayback Machinesuper().method

Véase también

Referencias

Enlaces externos