Cerca nel blog

giovedì 18 giugno 2015

PROGRAMMAZIONE AD OGGETTI IN ABAP - LEZIONE NR. 2

INCAPSULAMENTO

Con il termina incapsulamento, si indica la proprietà degli oggetti di incorporare al loro interno sia gli attributi che i metodi, cioè le caratteristiche e i comportamenti dell’oggetto.
Un oggetto viene utilizzato attraverso i metodi che esso mette a disposizione.
Per ogni metodo vengono indicati anche il numero e il tipo dei parametri di input e di output.

EREDITA’

L’eredità è lo strumento che permette di costruire nuove classi utilizzando quelle già sviluppate.
Quando una classe viene creata attraverso il meccanismo di ereditarietà a partire da un’altra classe, essa riceve in eredità tutti gli attributi ed i metodi della classe generatrice.
La classe che è stata derivata da un’altra usando l’ereditarietà prende il nome di SOTTOCLASSE. La classe generatrice di una sottoclasse si chiama SUPERCLASSE.



Nell’ABAP tutte le classi possono essere rappresentate in un albero di discendenza.
Il nodo più alto di questo albero è rappresentato dalla superclasse OBJECT.
Se per una classe non viene specificata nessuna ereditarietà allora questa erediterà in maniera implica direttamente dalla superclasse OBJECT.
In ABAP, viene supportato solo l’ereditarietà singola, cioè una sotto classe eredita da una sola superclasse.
L’eredità, serve a definire nuove classi, derivate da altre, che ereditano gli attributi ed i metodi, con la possibilità di ridefinirli o di aggiungere di nuovi
In ABAP per definire una sottoclasse che eredita da una superclasse scriveremo:

CLASS <sottoclasse>DEFINITION INHERITING FROM <superclasse>

I componenti PUBLIC e PROTECTED della superclasse saranno visibili nella sottoclasse.
I componenti PRIVATE resteranno visibili solo nella superclasse.
E’ possibile assegnare ai componenti PRIVATE della sottoclasse gli stessi nomi di quelli della superclasse.
I componenti STATIC (public e protected) di una superclasse sono visibili dalla sottoclasse.
Si può accedere ad un componente STATIC utilizzando entrambi le classi:

Super_classe=>attributo_statico
oppure
Sotto_classe=>attributo_statico

Una classe definita ABSTRACT non può essere istanziata, e quindi per poterla usare deve essere ereditata da una sottoclasse.
Si può comunque accedere ai componenti STATIC di una classe ABSTRACT.
Se un metodo viene definito ABSTRACT allora tutta la classe diventa ABSTRACT.

METHODS <metodo> ABSTRACT.

Un metodo ABSTRACT deve essere ridefinito all’interno della sottoclasse.

METHODS <metodo> REDEFINITION.

Una classe ABSTRACT può dichiarare e implementare metodi non astratti, questo permette di utilizzare questi metodi in una sottoclasse senza doverli ridefinire.
Una classe definita FINAL non può essere ereditata. Tutti i suoi metodi sono da considerarsi FINAL e NON devono essere dichiarati come FINAL.
Un metodo definito FINAL non può essere ridefinito in una sottoclasse.

METHODS <metodo> FINAL.

Se in una classe c’è un metodo FINAL, la classe può essere ereditata ma quel metodo non può essere ridefinito.
Un qualsiasi metodo non FINAL può essere ridefinito nella sottoclasse utilizzando la parola REFEFINITION.
I parametri del metodo tuttavia restano gli stessi definiti nella superclasse.
Ridefinire un metodo costruttore.
Il metodo CONSTRUCTOR non segue le regole di ridefinizione normali:

  •  Il CONSTRUCTOR viene ereditato automaticamente dalla superclasse OBJECT e quindi non essere definito nella CLASSE..DEFINITION.
  • Se si desidera ri-definirlo esso è l’unico metodo che può avere indicati dei parametri di import perché deve essere dichiarato nella CLASS…DEFINITION.
  • Quando una sottoclasse eredita da una superclasse in cui è stato ri-definito il metodo CONSTRUCTOR essa può a sua volta ri-definirlo.
  • Per ridefinire il  CONSTRUCTOR in una sottoclasse si seguono le stesse regole per ri-definirlo nella superclasse.
  • Il CONSTRUCTOR deve essere definito nella CLASSE..DEFINITION.
  • I parametri del CONSTRUCTOR della sottoclasse possono essere differenti da quelli definiti nella superclasse.
  • Nella CLASS….IMPLEMENTATION non si deve usare REDEFINITION.
  • L’unica regola quando si ri-definisce un metodo CONSTRUCTOR in una sottoclasse è che all’interno dell’implementazione deve essere richiamato il  CONSTRUCTOR della superclasse
 CALL METHOD SUPER=>constructor
                EXPORTING param1 = param.
  • I CONSTRUCTOR static funzionano in maniera molto simile a quelli instance .
  • I CONSTRUCTOR static non possono mai avere parametri.
  • Se un CONSTRUCTOR static viene ri-definito all’interno di una sottoclasse non è necessario richiamare il CONSTRUCTOR della superclasse perché questo avviene in automatico.
REFERENZIAZIONE E UTILIZZO DEGLI OGGETTI:

Ad un oggetto referenziato ad una superclasse possono essere attribuiti i valori di un oggetto di una sua sottoclasse.
Tuttavia esso potrà utilizzare solo i componenti presenti nella superclasse.

DATA:  obj1 TYPE REF TO class1,
obj2 TYPE REF TO class2.

CREATE OBJECT obj2.
obj1 = obj2.
obj1->component_obj1.                            CORRETTO
obj1->component_obj2.                            ERRATO

Durante la CREATE OBJETC può essere specificata la referenziazione alla classe con cui l’oggetto viene istanziato.
Questo modifica solo i componenti instance mentre quelli static restano referenziati alla classe presente nella dichiarazione.

DATA:  obj1 TYPE REF TO class1,
obj2 TYPE REF TO class2.

CREATE OBJECT obj1 TYPE class2.
CREATE OBJECT obj2.
obj1 = obj2.
obj1->component_obj1.                            CORRETTO
obj1->component_obj2.                            CORRETTO

L’attribuzione dei valori di una sottoclasse alla sua superclasse viene definito “narrowing cast.
Il narrowing cast è permesso e non genera errori di consistenza.
L’attribuzione dei valori di una superclasse  ad una sottoclasse viene definito “widening cast.
Il widening cast generalmente non è permesso e può generare errori di consistenza.
Per realizzare un widening cast bisogna usare l’operatore di assegnazione ?=

obj2 = obj1.                                                      ERRATO
obj2 ?= obj1.                                                    CORRETTO

Inoltre bisogna definire il controllo della condizione di errore:

CATCH SYSTEM-EXCEPTIONS.
MOVE_CAST_ERROR = 4.
Obj2 = obj1.
ENDCATCH.

POLIMORFISMO

Il polimorfismo indica la possibilità per i metodi di assumere forme, cioè implementazioni, diverse all’interno della gerarchia delle classi.
Utilizzando le proprietà del narrowing cast unite al polimorfismo potremo richiamare un metodo da un oggetto utilizzando a seconda delle necessità implementazioni differenti.

CLASS super_class DEFINITION.
…………………………………….
METHODS test_method.
ENDCLASS.

CLASS sub_class_one DEFINITION INHERITING FROM super_class.
…………………………………….
METHODS test_method REDEFINTION.
ENDCLASS.

CLASS sub_class_two DEFINITION INHERITING FROM super_class.
…………………………………….
METHODS test_method REDEFINTION.
ENDCLASS.

DATA: supr_obj TYPE REF TO super_class,
                Sub1_obj TYPE REF TO sub_class_one,
                Sub2_obj TYPE REF TO sub_class_two.

START-OF-SELECTION.
                CREATE OBJECT Sub1_obj.
                CREATE OBJECT Sub2_obj.
                Supr_obj = sub1_obj.

                CALL METHOD supr_obj->test_method.
                Supr_obj = sub2_obj.
CALL METHOD supr_obj->test_method.

INTERFACCE

L’ABAP non permette l’eredità multipla. Per aggirare questo limite si posso usare le interfacce.
Le interfacce sono simili alle classi ABSTRACT, ma hanno solo la parte della definizione.
Le interfacce sono definite come strutture indipendenti:

INTERFACE <nome_interfaccia>.
               ……………………….
ENDINTERFACE.

Un interfaccia può contenere sia componenti instance che static.
All’interno di un interfaccia tutti i componenti sono automaticamente PUBLIC e non si deve definire esplicitamente la sezione.
In un interfaccia è possibile definire i metodi ma non la loro implementazione.
Similmente a come una sottoclasse implementa i metodi di una classe astratta, così tutte  le classi che usano l’interfaccia devono implementare i metodi.
In ogni classe si possono implementare una o più interfacce.
Più classi possono implementare la stessa interfaccia.
Un interfaccia deve essere dichiarata nella sezione public della classe che vuole usarla

INTERFACE <nome_interfaccia>.

In questo modo tutti i componenti dell’interfaccia vengono aggiunti alla classe.
Le classi che usano l’interfaccia devono implementare tutti i metodi in essa definiti.
Un’interfaccia può contenere a sua volta un’altra interfaccia 

INTERFACE <nome_interfaccia1>.
               ……………………….
ENDINTERFACE.

INTERFACE <nome_interfaccia2>.
               ……………………….
               INTERFACE <nome_interfaccia1>.
ENDINTERFACE.

Quando una classe usa un’interfaccia che ne contiene un’altra deve implementare ogni metodo di ognuna delle due interfacce che ne contiene un’altra deve implementare ogni metodo di ognuna delle due interfacce definite.

In nome completo di un metodo di un interfaccia all’interno di una classe o di un’altra interfaccia è:

nome_interfaccia~nome_metodo

Al fine di semplificare l’accesso ai moduli è possibile definire degli ALIAS

ALIASES metodo FOR nome_interfaccia~nome_metodo

Gli ALIAS permettono di accedere ad un metodo di un interfaccia in modo diretto.

CALL METHOD oggetto->metodo.

All’interno dell’implementazione della classe tuttavia i metodi devono sempre essere richiamati con il nome completo
Come per le classi anche le interfacce possono essere usate per referenziare un oggetto.
E’ possibile eseguire il narrow cast anche attraverso un interfaccia

INTERFACE    interf1.
               METHODS: met1.
ENDINTERFACE.

CLASS c_classe1 DEFINITION.
               PUBLIC SECTION.
               INTERFACES:   interf1.
ENDCLASS.

CLASS c_classe1 IMPLEMENTATION.
               METHOD interf1~met1.
…………………
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
DATA:  ogg_ref TYPE REF to c_classe1,
int_ref TYPE REF to interf1.

CREATE OBJECT ogg_ref.
CALL METHOD: ogg_ref->interf1~met1.
int_ref = ogg_ref.
CALL METHOD: int_ref-> met1.

Un interfaccia utilizzata in una superclasse viene ereditata dalla sottoclasse e questa può implementare i metodi in modo differente.

EVENTI

Gli eventi servono a gestire gli stati di un oggetto/classe e le loro variazioni in seguito a determinate condizioni.
Un evento può essere STATIC e quindi riferito in modo generico alla classe o INSTANCE e quindi proprio dell’oggetto.
Un evento può essere dichiarato come PUBLIC, PROTECTED o PRIVATE.
Gli eventi possono anche essere definiti all’interno di un interfaccia ed in questo caso saranno obbligatoriamente PUBLIC.
Una classe può definire un metodo per generare un evento.


La stessa classe o un’altra classe può definire un altro metodo per gestire l’evento.
Un evento deve essere definito nella sezione DEFINITION della classe.

EVENTS <nome_evento>.

Un evento può avere solo parametri di EXPORTING e non deve essere implementato nella sezione di IMPLEMENTATION.
Un evento può essere generato da qualsiasi metodo all’interno della classe con l’istruzione.

RAISE EVENT <nome_evento>.

Un volta generato l’evento questo deve essere gestito per mezzo di un altro metodo
Qualsiasi classe può definire un metodo per gestire un evento sia che questo sia generato dalla stessa classe che da un’altra.
Un evento può avere diversi metodi di gestione a lui associati.
I metodi che gestiscono un evento devono essere definiti come:

METHODS: <nome_metodo> FOR EVENT <nome_evento> OF CLASS <nome_classe>

oppure

METHODS: <nome_metodo> FOR EVENT <nome_evento> OF INTERFACE 
<nome_interfaccia>

I metodi per la gestione dell’evento hanno solo parametri di IMPORTING.
I parametri che sono dichiarati con l’evento vengono passati al metodo di gestione dell’evento.
Tuttavia ogni metodo di gestione può decidere quali parametri passati dall’evento utilizzare.
I metodi che gestiscono un evento non possono essere richiamati con una CALL METHOD.
Essi vengono richiamati in automatico quando l’evento associato viene generato.
Dopo che un evento è stato generato tutti i metodi di gestione dichiarati vengono eseguiti prima che si passi all’istruzione successiva.
La sequenza con cui i metodi di gestione vengono eseguiti è la stessa in cui sono stati dichiarati.
Il processo di registrazione è dinamico, cioè viene istituito il collegamento in fase di runtime.
Per dichiarare il gestore di un evento si usa l’istruzione:

SET HANDLER oggetto->metodo_gest_evento FOR oggetto.

I metodi per la gestione di un evento possono di volta in volta essere “attivati” o “disattivati”.
Per attivare o disattivare un metodo di gestione si utilizza l’attributo ACTIVATION dell’istruzione  SET HANDLER.

SET HANDLER oggetto->metodo_gest_evento FOR oggetto ACTIVATION = ‘X’. (ATTIVAZIONE)

SET HANDLER oggetto->metodo_gest_evento FOR oggetto ACTIVATION = ‘’.  (DISATTIVAZIONE)

A runtime viene definita una struttura invisibile che accoglierà la lista dei metodi di gestione degli eventi e la loro sequenza di esecuzione
Un metodo per la gestione di un evento può a sua volta generare un altro evento.

 


Nessun commento:

Posta un commento