Переопределить атрибуты в классах ABAP? - PullRequest
1 голос
/ 15 октября 2019

скажем, я создал класс ZCL_WORKORDER_GENERIC с одним атрибутом, который представляет собой таблицу из ZCL_OPERATIONS_GENERIC объектов.

Теперь я хотел бы создать новый класс ZCL_WORKORDER_SPECIFIC1, наследующийся от первого, носписок операций также должен быть переопределен классом ZCL_OPERATIONS_SPECIFIC1.

Каков наилучший способ добиться этого в ABAP?

Ответы [ 2 ]

3 голосов
/ 15 октября 2019

Допустим, у вас есть

CLASS zcl_workorder_generic DEFINITION.
  PROTECTED SECTION.
    DATA operations TYPE REF TO zcl_operations_generic.
ENDCLASS.

Тогда вы можете легко получить

CLASS zcl_workorder_specific1 DEFINITION INHERITING FROM zcl_workorder_generic.
ENDCLASS

, и этот подкласс, естественно, будет иметь доступ к operations, напечатанному как zcl_operations_generic.

Тогда ваши конкретные операции могут быть

CLASS zcl_operations_specific1 DEFINITION INHERITING FROM zcl_operations_generic.
ENDCLASS.

В объектно-ориентированном проектировании zcl_operations_specific1 должен быть истинным подклассом zcl_operations_generic. Если вы чувствуете необходимость добавлять / изменять методы к ~specific1, которые не являются частью ~generic, ваш объектно-ориентированный дизайн неисправен, поскольку он нарушает принцип замены Лискова . «Неправильно» означает, что вы все равно можете заставить его работать каким-то образом с большим количеством CAST-ов, но вы будете работать против своего дизайна, вместо того, чтобы позволять себе увлекаться им.

В любом случае, вы должны добавить интерфейсы. Наследование - это средство для обмена кодом между реализациями. Интерфейсы объявляют контракты между классами и дают вам больше независимости, например, при написании модульных тестов.

2 голосов
/ 17 октября 2019

Как правило, вы не можете переопределить атрибуты, это запрещено моделью ABAP OO.

Однако вы можете сделать следующий трюк: объявить атрибут вашего суперкласса типа DATA (aka объект данных ) и затем назначьте ему любой тип в подклассе, который расширяет ваш суперкласс.

При условии, что у вас есть два типа операций, которые однозначно идентифицируют себя: zcl_operations_generic :

CLASS zcl_operations_generic DEFINITION.
  PUBLIC SECTION.
    DATA l_wheel TYPE char5 VALUE 'wheel'.
  METHODS: identify_me.
ENDCLASS.

CLASS zcl_operations_generic IMPLEMENTATION.
  METHOD identify_me.
    WRITE: `I am `, condense( cl_abap_classdescr=>get_class_name( me ) ), `and I have a`, l_wheel.
  ENDMETHOD.
ENDCLASS.

и более конкретно zcl_operations_specific1

CLASS zcl_operations_specific1 DEFINITION.
  PUBLIC SECTION.
    DATA l_wheel TYPE char10 VALUE 'truckwheel'.
  METHODS: who_am_i.
ENDCLASS.

CLASS zcl_operations_specific1 IMPLEMENTATION.
  METHOD who_am_i.
    WRITE: `I am `, condense( cl_abap_classdescr=>get_class_name( me ) ), `and I have a`, l_wheel.
  ENDMETHOD.
ENDCLASS.

Затем при создании общего рабочего задания zcl_workorder_generic вы указываете операциюmr_data как универсальный тип и выполните необходимые инициализации типа в конструкторе и методе:

CLASS zcl_workorder_generic DEFINITION.
  PUBLIC SECTION.
    DATA mr_data TYPE REF TO data.
    METHODS initialize EXPORTING out_order TYPE ANY.
    METHODS constructor.
ENDCLASS.

CLASS zcl_workorder_generic IMPLEMENTATION.
  METHOD initialize.
    FIELD-SYMBOLS: <lr_data> TYPE REF TO zcl_operations_generic.
    ASSIGN mr_data->* TO <lr_data>.
    CREATE OBJECT <lr_data>.
    out_order = <lr_data>.
  ENDMETHOD.
  METHOD constructor.
    CREATE DATA mr_data TYPE REF TO zcl_operations_generic.
  ENDMETHOD.
ENDCLASS.

и в определенном рабочем порядке zcl_workorder_specific1 вам следует переопределить методы конструктора / инициализации для нового типа:

CLASS zcl_workorder_specific1 DEFINITION INHERITING FROM zcl_workorder_generic.
  PUBLIC SECTION.
    METHODS initialize REDEFINITION.
    METHODS constructor.
ENDCLASS.

CLASS zcl_workorder_specific1 IMPLEMENTATION.
  METHOD initialize.
    FIELD-SYMBOLS: <lr_data> TYPE REF TO zcl_operations_specific1.
    ASSIGN mr_data->* TO <lr_data>.
    CREATE OBJECT <lr_data>.
    out_order = <lr_data>.
  ENDMETHOD.
  METHOD constructor.
    super->constructor( ).
    CREATE DATA mr_data TYPE REF TO zcl_operations_specific1.
  ENDMETHOD.
ENDCLASS.

Затем вы можете создать такие экземпляры ваших заказов, а затем проверить правильность создания атрибутов. By вызывая соответствующие методы атрибута:

START-OF-SELECTION.

  DATA: generic TYPE REF TO zcl_operations_generic.
  DATA(lr_work_order) = NEW zcl_workorder_generic( ).
  lr_work_order->initialize( IMPORTING out_order = generic ).
  generic->identify_me( ).

  WRITE: /.

  DATA: specific TYPE REF TO zcl_operations_specific1.
  lr_work_order = NEW zcl_workorder_specific1( ).
  lr_work_order->initialize( IMPORTING out_order = specific ).
  specific->who_am_i( ).

Но это просто хитрый обходной путь, и я согласен с тем, что переопределение атрибутов Florian - это плохой подход, который не должен использоваться.

...