Analizar y probar el código
Uso correcto de tipos de datos y conversiones de tipos
Campos de caracteres de procesamiento
Uso de la transferencia de código en ABAP SQL
Mejora del rendimiento de la tabla interna
Implementar verificaciones de autorización
Diseño de código orientado a objetos efectivo
Definir y trabajar con clases de excepción
Añadir documentación al código ABAP

Implementación de la herencia

Objective

After completing this lesson, you will be able to implemente una clase especializada.

Implementación de herencia

Vea este video para comprender el concepto de clases generales y más especializadas.

Herencia - La relación "Es A"

En el modelado hablamos de «especialización». La implementación de esta relación en un lenguaje de programación utiliza el concepto de herencia, en el que una nueva clase (la subclase) se deriva de una clase existente (la clase superior). Una prueba fiable para ver si existe una relación de herencia genuina entre dos clases es intentar decir "una subclase es una clase superior". Si esta afirmación es claramente verdadera, existe una relación de herencia. Si claramente no es cierto, o incluso suena un poco extraño, usted no tiene una relación de herencia y no debe implementar una ya que probablemente causará problemas más abajo en la línea. Al probar nuestro modelo, podemos decir definitivamente que "un avión de carga es un avión " y "un avión de pasajeros es un avión".

Una clase que hereda de una clase superior contiene automáticamente todos los componentes de la clase superior. Así, por ejemplo, la clase de avión de pasajeros tiene un fabricante y un tipo al igual que un avión. Esto no debería sorprender, ya que un avión de pasajeros es un avión. Lo que al principio puede parecer sorprendente es que la clase de avión de pasajeros no pueda acceder a su propio fabricante y tipo. Ello se debe al hecho de que son atributos privados de la clase superior y, como tales, no son accesibles para la subclase. Más adelante aprenderá una forma de permitir que una subclase acceda a los componentes de una clase superior sin hacerlos totalmente públicos.

Definición de una relación de herencia

En ABAP puede implementar la herencia utilizando el suplemento INHERITING FROM en la definición de clase sentencia. En este ejemplo, la clase de avión de pasajero se define como una subclase de la clase de avión. Tenga en cuenta que la subclase conoce su clase superior, pero la clase de avión no tiene idea de qué subclases tiene (si las hay).

Una subclase puede incluir solo una clase superior directa.

Una clase superior: cualquier número de subclases

La clase de avión puede tener cualquier número de subclases, pero no sabe nada de ellas.

Cada subclase tiene una única clase superior directa. Conoce su clase superior, pero no tiene información sobre ninguna clase hermana (otras clases que se derivan de la misma clase superior). En nuestro ejemplo, la clase de avión de pasajeros no tiene conocimiento de la clase de avión de carga.

Cómo ampliar una subclase

Una vez que haya declarado una subclase, debe añadirle componentes nuevos o modificar los componentes existentes. Esto es lo que convierte la mera copia de la clase de avión en un avión de pasajeros o un avión de carga. Gracias a la herencia, no es necesario implementar la clase desde cero; simplemente la amplía con los nuevos componentes que necesita.

Existen tres maneras de realizar esta tarea:

Agregar nuevos componentes: puede declarar nuevos atributos, tipos, constantes y métodos en la clase. Sus nombres no debe estar en conflicto con otros nombres que ya se han utilizado para declarar componentes en la clase superior. También debe asegurarse de que los componentes nuevos solo son relevantes para la subclase y no para todas las especializaciones de la clase superior. Si declara un atributo o método nuevo que, por lo general, es relevante, deberá moverlo a la clase superior.

Redefinir métodos: cuando llama un método heredado, el sistema de tiempo de ejecución ejecuta la implementación del método desde la clase superior. Sin embargo, esta implementación no puede tener en cuenta componentes nuevos que ha declarado en la subclase. En este caso, se puede volver a definir el método. Esto significa que puede asignarle una implementación nueva que es relevante para la subclase.

Añadir un constructor nuevo: Los constructores garantizan que las nuevas instancias de la clase se initalicen correctamente. Cuando crea una instancia de una subclase, el sistema de tiempo de ejecución siempre ejecuta el constructor de la clase superior. Esto garantiza, por ejemplo, que un avión de pasajeros tenga un fabricante y un tipo del mismo modo que cualquier otro avión. Sin embargo, el constructor de la clase superior no puede inicializar atributos de la subclase, ya que no sabe que existen. Por este motivo, puede definir un constructor nuevo para la subclase.

Declaración de componentes nuevos

Puede ampliar una subclase declarando componentes nuevos. Estas son visibles para la propia clase, pero no para la clase superior, y tampoco para ninguna otra clase que herede de la misma clase superior. Por lo tanto, debe considerar si los componentes nuevos solo son relevantes en la clase actual o si realmente se deben declarar en la clase superior.

Componentes protegidos

Aunque una subclase contenga todos los atributos de su clase superior, no está permitido acceder a los componentes privados directamente por sí misma. En ocasiones esto resulta necesario; sin embargo, en otras ocasiones es necesario que una clase superior deje que sus subclases accedan a atributos o métodos concretos sin hacerlos totalmente públicos. Puede hacerlo declarándolos en la sección protegida. Los componentes protegidos no solo están visibles dentro de la propia clase, sino también para todas las subclases.

En la definición de clase se introduce la sección protegida mediante la sentencia PROTECTED SECTION. Siempre debe declarar las secciones de visibilidad en la secuencia PUBLIC SECTION, PROTECTED SECTION, PRIVATE SECTION.

Puede mover un componente existente de una clase utilizando una corrección rápida. Para ello, sitúe el cursor en el nombre del componente en ADT y pulse Ctrl + 1 y, a continuación, seleccione la solución rápida Proteger <elemento>.

Mover un componente privado a la sección protegida es una modificación compatible: ha ampliado la visibilidad del componente. Sin embargo, proteger un componente público es una modificación incompatible y podría provocar errores de sintaxis. Esto se debe a que ha restringido la visibilidad del componente que ya podría haberse utilizado fuera de la jerarquía de herencia.

Redefinición de métodos

Las clases superiores suelen contener métodos que desea utilizar en una subclase, pero sus implementaciones son inapropiadas, ya que no tienen en cuenta la naturaleza concreta de la subclase. Por ejemplo, el método get_attributes de la clase de avión no puede devolver atributos definidos en la clase de avión de pasajero. Sin embargo, la clase de avión de pasajeros aún necesita un método get_attributes.

En ABAP, puede resolver este problema redefiniendo el método de instancia get_attributes. Al redefinir un método, puede escribir una nueva implementación para él en la subclase que tiene en cuenta cosas que solo la subclase puede saber. Sin embargo, la definición del método sigue siendo exactamente la misma. Debe seguir estas reglas:

  • El método conserva el mismo nombre.
  • Puede indicar que desea redefinir el método declarándolo en la subclase con el suplemento REDEFINITION.
  • El método tiene la misma visibilidad que en la clase superior.
  • No debe cambiar la firma del método.

No puede redefinir un método estático.

Implementación de la redefinición

Al implementar la redefinición de un método, puede llamar la implementación en la clase superior. Esto se consigue mediante la referencia de objeto implícita «súper», que muestra la clase superior dentro de la instancia actual. De este modo, puede reutilizar la implementación de método de la clase superior y luego añadirla en su propia implementación.

No es necesario declarar la variable de referencia «súper». Está disponible automáticamente dentro de la implementación o de los métodos redefinidos.

Llamar el método en la clase superior de esta manera es opcional. A veces será una buena idea, mientras que en otras ocasiones no aportará nada.

Nueva definición de constructor

En una subclase puede definir un constructor nuevo. A diferencia de las redefiniciones de método, un constructor puede tener su propia firma. La firma de un constructor suele contener los mismos parámetros que el constructor de la clase superior, además de sus propios parámetros nuevos. Esto se debe a que el nuevo constructor de instancia tiene dos tareas: primero llamar al constructor de la clase superior y, a continuación, encargarse de initalizar sus propios atributos que son específicos de la subclase.

De la misma manera que se puede definir un constructor nuevo, también puede definir una constructor estático nuevo en una subclase.

Rol del constructor

El constructor de una subclase tiene dos funciones: debe asegurarse de que los componentes de la clase superior se inicialicen correctamente, y después de eso, puede establecer los valores iniciales de los atributos de subclase.

En nuestro ejemplo, dado que un avión de pasajeros es un avión, no puede haber ninguna instancia de avión de pasajeros a menos que el constructor de la clase de avión se haya ejecutado correctamente para establecer el fabricante y el tipo del nuevo avión de pasajeros. Solo después de esto, la clase de avión de pasajeros puede fijar sus propios atributos.

Por lo tanto, el constructor de la subclase debe tener la capacidad de fijar no solo sus propios atributos, sino de transferir los valores requeridos para al constructor de la clase superior. Este es el motivo por el que la firma del constructor en la subclase suele contener toda la firma del constructor necesaria para llamar.

Secuencia de implementación de constructor nuevo

En la implementación del constructor nuevo existe una secuencia concreta de operaciones que debe observar. El evento más importante es la llamada al constructor de la clase superior. Esto es obligatorio y se llama el método mediante la referencia implícita «súper» del mismo modo que puede hacerlo al llamar la implementación original de un método redefinido. Una vez más, no es necesario declarar explícitamente super.

Antes de haber llamado el constructor de la clase superior, no debe tratar los componentes de instancia de la instancia que está en construcción. Puede tratar los componentes estáticos de la clase y verificar la exactitud de los parámetros de importación del constructor. Si no son correctos, cree una excepción.

Una vez que el constructor de la clase superior se ha ejecutado correctamente, puede tratar los componentes de instancia de su nueva instancia.

Secuencia de llamadas de constructor

El gráfico ilustra la secuencia en la que se llaman los constructores estáticos y los constructores de instancia. El ejemplo supone que un programa desea instanciar la clase de avión de pasajero y que la clase de avión no se ha abordado previamente.

Cuando el programa intenta crear una instancia de la clase de avión pasajero, el sistema de tiempo de ejecución llama automáticamente a los constructores estáticos secuencialmente, empezando por la parte superior de la jerarquía de herencia. Una vez ejecutados todos los constructores estáticos, el sistema del tiempo de ejecución llama el constructor de instancia de la subclase, que, a su vez, llama el constructor de instancia de la clase superior.

Pruébelo: implementación de herencia

  1. Cree una clase nueva que implemente la interfaz IF_OO_ADT_CLASSRUN.
  2. Cambie a la pestaña Tipos locales y copie el siguiente fragmento de código en el editor:
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
    CLASS lcl_plane DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF ts_attributes, name TYPE string, value TYPE string, END OF ts_attributes, * declare table - do not allow the same attribute to be used more than once tt_attributes TYPE SORTED TABLE OF ts_attributes WITH UNIQUE KEY name. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string. METHODS: get_Attributes RETURNING VALUE(rt_Attributes) TYPE tt_attributes. PROTECTED SECTION. DATA manufacturer TYPE string. DATA type TYPE string. PRIVATE SECTION. ENDCLASS. CLASS lcl_plane IMPLEMENTATION. METHOD constructor. manufacturer = iv_manufacturer. type = iv_type. ENDMETHOD. METHOD get_attributes. rt_attributes = VALUE #( ( name = 'MANUFACTURER' value = manufacturer ) ( name = 'TYPE' value = type ) ) . ENDMETHOD. ENDCLASS. CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_plane. PUBLIC SECTION. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string iv_cargo TYPE i. METHODS get_attributes REDEFINITION. private section. data cargo type i. ENDCLASS. CLASS lcl_cargo_plane IMPLEMENTATION. METHOD constructor. super->constructor( iv_manufacturer = iv_manufacturer iv_type = iv_type ). cargo = iv_cargo. ENDMETHOD. METHOD get_attributes. * method uses protected attributes of superclass rt_attributes = value #( ( name = 'MANUFACTURER' value = manufacturer ) ( name = 'TYPE' value = type ) ( name ='CARGO' value = cargo ) ). ENDMETHOD. ENDCLASS. CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_Plane. PUBLIC SECTION. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string iv_seats TYPE i. METHODS get_Attributes REDEFINITION. private section. data seats type i. ENDCLASS. CLASS lcl_passenger_plane IMPLEMENTATION. METHOD constructor. super->constructor( iv_manufacturer = iv_manufacturer iv_type = iv_type ). ENDMETHOD. METHOD get_attributes. * Redefinition uses call of superclass implementation rt_attributes = super->get_attributes( ). rt_Attributes = value #( base rt_attributes ( name = 'SEATS' value = seats ) ). ENDMETHOD. ENDCLASS.
  3. Active la clase pulsando Ctrl + F3.
  4. Familiarícese con el código fuente utilizando características del editor como la documentación F2 y las funciones de navegación.

    Nota

    No hay ningún código ejecutable en este ejemplo.

Uso de componentes abstractos y finales

Puede declarar una clase como abstracta. Esto significa que un programa no puede instanciarlo. En nuestro ejemplo con aviones, aviones de pasajeros y aviones de carga, puede decidir que, en el mundo real, solo hay aviones de pasajeros y aviones de carga. Sin embargo, desde el punto de vista del modelado de software, es útil tener la clase lcl_plane para mantener los componentes que tienen en común los aviones de carga y los aviones de pasajeros. Al utilizar la clase abstracta, puede implementar todos los componentes comunes en la clase plana sin tener que preocuparse de que alguien pueda crear instancias de la clase por error.

Si una clase es abstracta, aún puede acceder a sus componentes estáticos. Estas son:

  • Métodos estáticos
  • Atributos estáticos
  • Constantes
  • Definiciones de tipo

Aunque puede implementar los métodos de una clase abstracta, también puede declarar un método individual como abstracto. En este caso, no hay ninguna implementación para él en la clase en la que se declara. Tenga en cuenta que solo puede declarar un método abstracto en una clase abstracta.

Las subclases de la clase abstracta solo se pueden instanciar una vez redefinido el método abstracto.

Puede declarar una clase como FINAL. Esto significa que no puede tener subclases.

En una clase que no es final en sí misma, puede declarar los métodos como finales. Esto significa que, aunque la clase en sí puede tener subclases, el método en sí no se puede redefinir. Puede hacerlo si un método contiene una verificación de autorización. De lo contrario, una subclase podría redefinir el método y omitir la verificación de autorización.

Implementar la herencia

Observa que sus clases locales LCL_PASSENGER_FLIGHT y LCL_CARGO_FLIGHT tienen mucho en común y contienen implementaciones redundantes. Se da cuenta de que, desde una perspectiva de modelo, puede percibir los vuelos de pasajeros y los vuelos de carga como dos especializaciones de vuelos en general. Por lo tanto, introduce una clase superior común LCL_FLIGHT con las definiciones e implementaciones comunes.

Modelo:

  • /LRN/CL_S4D401_ACS_AUTH_CHECK (clase global)

Solución:

  • /LRN/CL_S4D401_OOS_INHERITANCE (clase global)

Tarea 1: Copiar plantilla (opcional)

Copie la clase de modelo /LRN/CL_S4D401_ACS_AUTH_CHECK. Si ha finalizado el ejercicio anterior, puede omitir esta tarea y continuar editando su clase ZCL_##_SOLUTION.

Pasos

  1. Copie la clase /LRN/CL_S4D401_ACS_AUTH_CHECK en una clase de su propio paquete (nombre sugerido: ZCL_##_SOLUTION, donde ## representa su número de grupo).

    1. En el Explorador de proyectos, haga clic con el botón derecho en la clase /LRN/CL_S4D401_ACS_AUTH_CHECK para abrir el menú contextual.

    2. En el menú contextual, seleccione Duplicar....

    3. Introduzca el nombre del paquete en el campo Paquete. En el campo Nombre, introduzca ZCL_##_SOLUTION, donde ## representa su número de grupo.

    4. Seleccione Siguiente.

    5. Confirme la orden de transporte y seleccione Finalizar.

  2. Active la copia.

    1. Pulse Ctrl + F3 para activar la clase.

Tarea 2: Definir la clase superior

Defina una nueva clase local LCL_FLIGHT y deje que las clases locales LCL_PASSENGER_FLIGHT y LCL_CARGO_FLIGHT hereden de ella. Compare las dos subclases y mueva los atributos y las definiciones de método que son idénticos en ambas clases a la clase superior.

Pasos

  1. En su clase global ZCL_##_SOLUTION, utilice un modelo de código para definir una nueva clase local LCL_FLIGHT.

    Nota

    Asegúrese de definir la nueva clase al principio del código fuente en la pestaña Tipos locales para poder hacer referencia a ella en las clases locales existentes.
    1. En su clase global ZCL_##_SOLUTION, cambie a la pestaña Tipos locales.

    2. Al principio del código fuente, escriba lcl y pulse Ctrl + Espacio para invocar la finalización del código.

    3. En la lista de finalizaciones sugeridas, seleccione lcl - Clase local.

    4. Mientras lcl_ aún está resaltado, introduzca lcl_flight para ajustar el nombre de clase en la definición y la parte de implementación.

    5. El modelo de código debería haber añadido el siguiente código:

      ABAP
      123456789
      CLASS lcl_flight DEFINITION CREATE PRIVATE. PUBLIC SECTION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_flight IMPLEMENTATION. ENDCLASS.
  2. Asegúrese de que no sea posible crear instancias de LCL_FLIGHT.

    1. Elimine el suplemento CREATE PRIVATE y sustitúyalo por un suplemento ABSTRACT.

    2. Asegúrese de que su código tenga un aspecto similar al siguiente:

      ABAP
      12
      * CLASS lcl_flight DEFINITION CREATE PRIVATE. CLASS lcl_flight DEFINITION ABSTRACT.
  3. Deje que la clase local LCL_PASSENGER_FLIGHT herede de la clase local LCL_FLIGHT.

    1. Desplácese hacia abajo hasta la parte de definición de la clase local LCL_PASSENGER_FLIGHT.

    2. Ajuste el código de la siguiente manera:

      ABAP
      12
      CLASS lcl_passenger_flight DEFINITION INHERITING FROM lcl_flight.
  4. Corrija los errores de sintaxis "En el método constructor, solo se puede acceder a los atributos de instancia ... después de llamar al constructor de la clase superior ..." añadiendo super->constructor( ). al principio de la implementación del método CONSTRUCTOR en la subclase LCL_PASSENGER_FLIGHT.

    Nota

    Veremos más detalladamente la lógica del constructor más adelante en este ejercicio.
    1. Ajuste el código de la siguiente manera:

      ABAP
      12
      METHOD constructor. super->constructor( ).
  5. Utilice una corrección rápida para mover ("pull-up") los siguientes componentes públicos de la subclase LCL_PASSENGER_FLIGHT a la clase superior LCL_FLIGHT:

    • Atributo carrier_id
    • ID de conexión de atributo
    • Atributo flight_date
    • Tipo de estructura ST_CONNECTION_DETAILS
    • Método GET_CONNECTION_DETAILS

    Nota

    Este paso provoca un error de sintaxis en la implementación del método GET_CONNECTION_DETAILS movido, porque accede a un componente que aún no está disponible en la clase superior LCL_FLIGHT. Este error se corregirá en el siguiente paso.
    1. En la parte de definición de la clase local LCL_PASSENGER_FLIGHT, sitúe el cursor en carrier_id y seleccione Ctrl + 1 para visualizar una lista de correcciones rápidas disponibles.

    2. En la lista de correcciones rápidas disponibles, seleccione Pull-Up carrier_id a la clase superior lcl_flight.

    3. Repita esto para los otros componentes enumerados anteriormente.

    4. La parte de definición de la clase superior LCL_FLIGHT ahora debería tener este aspecto:

      ABAP
      1234567891011121314151617181920212223
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. TYPES: BEGIN OF st_connection_details, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, departure_time TYPE /dmo/flight_departure_time, arrival_time TYPE /dmo/flight_departure_time, duration TYPE i, END OF st_connection_details. DATA carrier_id TYPE /dmo/carrier_id READ-ONLY. DATA connection_id TYPE /dmo/connection_id READ-ONLY. DATA flight_date TYPE /dmo/flight_date READ-ONLY. METHODS: get_connection_details RETURNING VALUE(r_result) TYPE st_connection_details. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS.
  6. Utilice una corrección rápida para mover ("pull-up") los siguientes componentes privados de la subclase LCL_PASSENGER_FLIGHT a la clase superior LCL_FLIGHT:

    • Tipo de plan de atributo
    • Atributo connection_details
    1. En la parte de definición de la clase local LCL_PASSENGER_FLIGHT, sitúe el cursor en planetype y seleccione Ctrl + 1 para visualizar una lista de correcciones rápidas disponibles.

    2. En la lista de correcciones rápidas disponibles, seleccione Pull-Up planetype to superclass lcl_flight.

    3. Repita esto para el atributo connection_details.

    4. La parte de definición de la clase superior LCL_FLIGHT ahora debería tener este aspecto:

      ABAP
      1234567891011121314151617181920212223242526
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. TYPES: BEGIN OF st_connection_details, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, departure_time TYPE /dmo/flight_departure_time, arrival_time TYPE /dmo/flight_departure_time, duration TYPE i, END OF st_connection_details. DATA carrier_id TYPE /dmo/carrier_id READ-ONLY. DATA connection_id TYPE /dmo/connection_id READ-ONLY. DATA flight_date TYPE /dmo/flight_date READ-ONLY. METHODS: get_connection_details RETURNING VALUE(r_result) TYPE st_connection_details. PROTECTED SECTION. DATA planetype TYPE /dmo/plane_type_id. DATA connection_details TYPE st_connection_details. PRIVATE SECTION. ENDCLASS.
  7. Deje que la clase local LCL_CARGO_FLIGHT herede de la clase local LCL_FLIGHT.

    1. Desplácese hasta la parte de definición de la clase local LCL_CARGO_FLIGHT.

    2. Ajuste el código de la siguiente manera:

      ABAP
      12
      CLASS lcl_cargo_flight DEFINITION INHERITING FROM lcl_flight.
  8. Comente o elimine las definiciones redundantes de la clase local LCL_CARGO_FLIGHT.

    Consejo

    Utilice los errores de sintaxis en la vista Problemas para navegar a las definiciones redundantes.
    1. En la vista Problemas, haga doble clic en el error de sintaxis Ya existe un tipo llamado "ST_CONNECTION_DETAILS".

    2. Elimine o comente la definición del tipo de estructura ST_CONNECTION_DETAILS en la clase local LCL_CARGO_FLIGHT.

    3. Repita esto para los otros componentes que ya están definidos en la clase superior LCL_FLIGHT.

    Nota

    No olvide eliminar o comentar también la implementación del método GET_CONNECTION_DETAILS.
  9. Corrija los errores de sintaxis "En el método constructor, solo se puede acceder a los atributos de instancia ... después de llamar al constructor de la clase superior ..." añadiendo super->constructor( ). al principio de la implementación del método CONSTRUCTOR en la subclase LCL_CARGO_FLIGHT.

    1. Ajuste el código de la siguiente manera:

      ABAP
      12
      METHOD constructor. super->constructor( ).

Tarea 3: Redefinir un método

Defina un método GET_DESCRIPTION en la clase superior y vuelva a definirlo en las subclases. Mueva las partes comunes de la implementación a la clase superior y conserve las partes específicas en las subclases.

Pasos

  1. En la clase superior LCL_FLIGHT, defina un método de instancia público GET_DESCRIPTION con los mismos parámetros que en las subclases.

    Consejo

    Copie la definición de método de una de las subclases.
    1. Ajuste el código de la siguiente manera:

      ABAP
      123456
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. METHODS get_description RETURNING VALUE(r_result) TYPE string_table.
  2. En las clases locales LCL_PASSENGER_FLIGHT y LCL_CARGO_FLIGHT, sustituya las definiciones del método GET_DESCRIPTION por redefiniciones.

    Consejo

    Utilice los errores de sintaxis en la vista Problemas para navegar a las definiciones de método.
    1. En la parte de definición de ambas subclases, ajuste el código de la siguiente manera:

      ABAP
      1234
      * METHODS get_description * RETURNING * VALUE(r_result) TYPE string_table. METHODS get_description REDEFINITION.
  3. Utilice una corrección rápida para añadir una implementación vacía para el nuevo método GET_DESCRIPTION a la clase local LCL_FLIGHT.

    1. En la definición de la clase local LCL_FLIGHT, sitúe el cursor en get_description y pulse Ctrl + 1 para invocar las correcciones rápidas disponibles. Como alternativa, puede seleccionar el icono de error con la bombilla en la parte izquierda del código.

    2. En la lista de sugerencias, seleccione Añadir implementación para get_description.

  4. En la clase local LCL_PASSENGER_FLIGHT, ajuste la implementación del método GET_DESCRIPTION. Al principio de la implementación, llame la implementación desde la clase superior y almacene el resultado en el parámetro r_result.

    1. Añada el código siguiente:

      ABAP
      1
      r_result = super->get_description( ).
  5. Mueva el código que gestiona los valores ​​de los siguientes atributos heredados de la subclase LCL_PASSENGER_FLIGHT a la implementación del método GET_DESCRIPTION en la clase superior LCL_FLIGHT: carrier_id, connection_id, flight_date, connection_detail s-airport_from_id, connection_details s-airport_to_id y planetype

    1. Resalte la declaración y la preparación de la variable local txt, así como las dos sentencias APPEND para la variable txt y el atributo planetype, y pulse Ctrl + C para copiar el fragmento de código en el portapapeles.

    2. Pulse Ctrl + < para añadir un signo de comentario al principio de las filas de código seleccionadas.

    3. Cambie a la implementación del método GET_DESCRIPTION en la clase local LCL_FLIGHT, coloque el cursor entre las sentencias METHOD … y ENDMETHOD y pulse Ctrl + V para insertar el fragmento de código.

    4. La implementación en la clase superior debería tener el siguiente aspecto:

      ABAP
      12345678910111213
      METHOD get_description. DATA txt TYPE string. txt = 'Flight &carrid& &connid& on &date& from &from& to &to&'(005). txt = replace( val = txt sub = '&carrid&' with = carrier_id ). txt = replace( val = txt sub = '&connid&' with = connection_id ). txt = replace( val = txt sub = '&date&' with = |{ flight_date DATE = USER }| ). txt = replace( val = txt sub = '&from&' with = connection_details-airport_from_id ). txt = replace( val = txt sub = '&to&' with = connection_details-airport_to_id ). APPEND txt TO r_result. APPEND |{ 'Planetype:'(006) } { planetype }| TO r_result. ENDMETHOD.
  6. En la clase local LCL_CARGO_FLIGHT, ajuste la implementación del método GET_DESCRIPTION según corresponda: llame la implementación heredada del método GET_DESCRIPTION y elimine o comente las sentencias APPEND redundantes.

    1. Ajuste el código de la siguiente manera:

      ABAP
      123456789101112
      METHOD get_description. r_result = super->get_description( ). * APPEND |Flight { carrier_id } { connection_id } on { flight_date DATE = USER } | && * |from { connection_details-airport_from_id } to { connection_details-airport_to_id }| * TO r_result. * APPEND |Planetype: { planetype }| * TO r_result. APPEND |Maximum Load: { maximum_load } { load_unit }| TO r_result. APPEND |Free Capacity: { get_free_capacity( ) } { load_unit }| TO r_result. ENDMETHOD.

Tarea 4: Añadir un constructor común

En la clase superior LCL_FLIGHT, defina un constructor de instancia con los parámetros de entrada que tienen en común los dos constructores de subclase. Ajuste la llamada del constructor de clase superior en las subclases para que reenvíen los parámetros comunes. A continuación, mueva las partes comunes de la lógica del constructor de los constructores de subclase al constructor de clase superior.

Pasos

  1. En la clase superior LCL_FLIGHT, defina un método CONSTRUCTOR que tenga los mismos parámetros de entrada que el CONSTRUCTOR de la subclase LCL_PASSENGER_FLIGHT.

    Consejo

    No hay una corrección rápida pull-up para los métodos de constructor de instancia. En su lugar, copie y pegue la definición de método de la subclase a la clase superior.
    1. Desplácese hasta la parte de definición de la clase local LCL_PASSENGER_FLIGHT.

    2. Seleccione la sentencia METHODS completa para el método CONSTRUCTOR y pulse Ctrl + C para copiar el fragmento de código en el portapapeles.

    3. Desplácese hasta la parte de definición de la clase local LCL_FLIGHT, coloque el cursor después de la sentencia PUBLIC SECTION y pulse Ctrl + V para insertar el fragmento de código desde el portapapeles.

  2. Ajuste la llamada del constructor de clase superior en las subclases. Transfiera los parámetros de importación al constructor de clase superior.

    Consejo

    Utilice los errores de sintaxis en la vista Problemas para navegar a las llamadas del constructor de clase superior.
    1. En ambos constructores de subclase, ajuste el código de la siguiente manera:

      ABAP
      123456
      METHOD constructor. super->constructor( i_carrier_id = i_carrier_id i_connection_id = i_connection_id i_flight_date = i_flight_date ).
  3. Utilice una corrección rápida para añadir una implementación vacía para el constructor de clase superior.

    1. En la definición de la clase local LCL_FLIGHT, sitúe el cursor en constructor y pulse Ctrl + 1 para invocar las correcciones rápidas disponibles.

    2. En la lista de sugerencias, seleccione Añadir implementación para constructor.

  4. Mueva las valoraciones para los atributos heredados carrier_id, connection_id y flight_date de los constructores de subclase al constructor de clase superior.

    1. Navegue a la implementación del método CONSTRUCTOR en la clase local LCL_PASSENGER_FLIGHT.

    1. Seleccione las valoraciones para los atributos heredados carrier_id, connection_id y flight_date y pulse Ctrl + C para copiar el fragmento de código en el portapapeles.

    2. Pulse Ctrl + < para añadir un signo de comentario al principio de las filas de código seleccionadas.

    3. Cambie a la implementación del método CONSTRUCTOR en la clase local LCL_FLIGHT, coloque el cursor entre METHOD … y ENDMETHOD y pulse Ctrl + V para insertar el fragmento de código.

    4. La implementación en la clase superior debería tener el siguiente aspecto:

      ABAP
      12345
      METHOD constructor. me->carrier_id = i_carrier_id. me->connection_id = i_connection_id. me->flight_date = i_flight_date. ENDMETHOD.
    5. Cambie a la implementación del método CONSTRUCTOR en la clase local LCL_CARGO_FLIGHT y elimine o comente las valoraciones redundantes.

  5. Active y pruebe su clase global como aplicación de consola. Depure la instanciación de la clase local LCL_PASSENGER_FLIGHT y la llamada del método GET_DESCRIPTION.

    1. Pulse Ctrl + F3.

    2. Pulse F9.