Classes e Objetos em ABAP
A Programação Orientada a Objetos (OOP) permite criar código mais modular, reutilizável e fácil de manter.
🔹 O que é uma Classe?
Uma classe é um modelo (template) que define: - Atributos (dados/variáveis) - Métodos (comportamentos/funções)
Um objeto é uma instância (exemplar) de uma classe.
🔹 Estrutura de uma Classe
CLASS lcl_pessoa DEFINITION.
PUBLIC SECTION.
" Atributos públicos
DATA: mv_nome TYPE string,
mv_idade TYPE i.
" Métodos públicos
METHODS:
set_nome IMPORTING iv_nome TYPE string,
get_nome RETURNING VALUE(rv_nome) TYPE string,
apresentar.
PRIVATE SECTION.
" Atributos privados
DATA: mv_saldo TYPE p DECIMALS 2.
" Métodos privados
METHODS: calcular_bonus RETURNING VALUE(rv_bonus) TYPE p DECIMALS 2.
ENDCLASS.
CLASS lcl_pessoa IMPLEMENTATION.
METHOD set_nome.
mv_nome = iv_nome.
ENDMETHOD.
METHOD get_nome.
rv_nome = mv_nome.
ENDMETHOD.
METHOD apresentar.
WRITE: / |Olá, eu sou { mv_nome } e tenho { mv_idade } anos.|.
ENDMETHOD.
METHOD calcular_bonus.
rv_bonus = mv_saldo * '0.10'.
ENDMETHOD.
ENDCLASS.
🔹 Criar e Usar Objetos
REPORT z_oo_exemplo.
" 1. Definir a classe (acima)
START-OF-SELECTION.
" 2. Declarar referência ao objeto
DATA: lo_pessoa TYPE REF TO lcl_pessoa.
" 3. Criar instância (objeto)
CREATE OBJECT lo_pessoa.
" 4. Usar o objeto
lo_pessoa->set_nome( 'Bruno' ).
lo_pessoa->mv_idade = 25.
lo_pessoa->apresentar( ).
" 5. Verificar se objeto existe
IF lo_pessoa IS BOUND.
WRITE: / 'Objeto existe e está ativo'.
ENDIF.
Saída:
Olá, eu sou Bruno e tenho 25 anos.
Objeto existe e está ativo
🔹 Sintaxe Moderna: NEW
" ✅ Sintaxe moderna (ABAP 7.40+)
DATA(lo_pessoa) = NEW lcl_pessoa( ).
lo_pessoa->set_nome( 'Ana' ).
lo_pessoa->mv_idade = 30.
" Inline com uso direto
NEW lcl_pessoa( )->set_nome( 'João' )->apresentar( ).
🔹 Visibilidade de Seções
| Seção | Acesso | Uso |
|---|---|---|
| PUBLIC | Dentro e fora da classe | Interface pública |
| PROTECTED | Classe e subclasses | Herança |
| PRIVATE | Apenas dentro da classe | Implementação interna |
CLASS lcl_conta DEFINITION.
PUBLIC SECTION.
METHODS:
depositar IMPORTING iv_valor TYPE p DECIMALS 2,
get_saldo RETURNING VALUE(rv_saldo) TYPE p DECIMALS 2.
PROTECTED SECTION.
DATA: mv_saldo TYPE p DECIMALS 2.
PRIVATE SECTION.
DATA: mv_senha TYPE string.
METHODS: validar_senha IMPORTING iv_senha TYPE string
RETURNING VALUE(rv_ok) TYPE abap_bool.
ENDCLASS.
CLASS lcl_conta IMPLEMENTATION.
METHOD depositar.
mv_saldo = mv_saldo + iv_valor.
ENDMETHOD.
METHOD get_saldo.
rv_saldo = mv_saldo.
ENDMETHOD.
METHOD validar_senha.
rv_ok = COND #( WHEN iv_senha = mv_senha THEN abap_true
ELSE abap_false ).
ENDMETHOD.
ENDCLASS.
🔹 Classes Locais vs Globais
Classes Locais
Definidas dentro de um programa (report, function group, etc.).
REPORT z_classe_local.
" Definição local
CLASS lcl_calculadora DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: somar IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_soma) TYPE i.
ENDCLASS.
CLASS lcl_calculadora IMPLEMENTATION.
METHOD somar.
rv_soma = iv_a + iv_b.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(lv_resultado) = lcl_calculadora=>somar( iv_a = 10 iv_b = 20 ).
WRITE: / lv_resultado.
Classes Globais
Criadas na SE24 ou SE80, reutilizáveis em todo o sistema.
" Usar classe global ZCL_UTILS
DATA(lo_utils) = NEW zcl_utils( ).
lo_utils->metodo_publico( ).
🔹 Métodos de Instância vs Métodos Estáticos
Métodos de Instância
Requerem um objeto (lo_obj->metodo()):
CLASS lcl_contador DEFINITION.
PUBLIC SECTION.
DATA: mv_contador TYPE i.
METHODS: incrementar.
ENDCLASS.
CLASS lcl_contador IMPLEMENTATION.
METHOD incrementar.
mv_contador = mv_contador + 1.
ENDMETHOD.
ENDCLASS.
" Uso
DATA(lo_cont1) = NEW lcl_contador( ).
lo_cont1->incrementar( ).
lo_cont1->incrementar( ).
WRITE: / lo_cont1->mv_contador. " 2
DATA(lo_cont2) = NEW lcl_contador( ).
lo_cont2->incrementar( ).
WRITE: / lo_cont2->mv_contador. " 1
Métodos Estáticos (CLASS-METHODS)
Não requerem objeto (lcl_classe=>metodo()):
CLASS lcl_utils DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
maiuscula IMPORTING iv_texto TYPE string
RETURNING VALUE(rv_result) TYPE string.
ENDCLASS.
CLASS lcl_utils IMPLEMENTATION.
METHOD maiuscula.
rv_result = to_upper( iv_texto ).
ENDMETHOD.
ENDCLASS.
" Uso (sem criar objeto)
DATA(lv_texto) = lcl_utils=>maiuscula( 'olá mundo' ).
WRITE: / lv_texto. " OLÁ MUNDO
🔹 Exemplo Completo: Sistema de Biblioteca
*&---------------------------------------------------------------------*
*& Report Z_OO_BIBLIOTECA
*&---------------------------------------------------------------------*
REPORT z_oo_biblioteca.
" ============ DEFINIÇÕES ============
CLASS lcl_livro DEFINITION.
PUBLIC SECTION.
DATA: mv_titulo TYPE string,
mv_autor TYPE string,
mv_isbn TYPE string,
mv_disponivel TYPE abap_bool.
METHODS:
constructor IMPORTING iv_titulo TYPE string
iv_autor TYPE string
iv_isbn TYPE string,
emprestar,
devolver,
get_info RETURNING VALUE(rv_info) TYPE string.
ENDCLASS.
CLASS lcl_biblioteca DEFINITION.
PUBLIC SECTION.
METHODS:
adicionar_livro IMPORTING io_livro TYPE REF TO lcl_livro,
listar_livros,
buscar_por_isbn IMPORTING iv_isbn TYPE string
RETURNING VALUE(ro_livro) TYPE REF TO lcl_livro.
PRIVATE SECTION.
DATA: mt_livros TYPE TABLE OF REF TO lcl_livro.
ENDCLASS.
" ============ IMPLEMENTAÇÕES ============
CLASS lcl_livro IMPLEMENTATION.
METHOD constructor.
mv_titulo = iv_titulo.
mv_autor = iv_autor.
mv_isbn = iv_isbn.
mv_disponivel = abap_true.
ENDMETHOD.
METHOD emprestar.
IF mv_disponivel = abap_true.
mv_disponivel = abap_false.
WRITE: / |Livro "{ mv_titulo }" emprestado com sucesso.|.
ELSE.
WRITE: / |Livro "{ mv_titulo }" já está emprestado.|.
ENDIF.
ENDMETHOD.
METHOD devolver.
mv_disponivel = abap_true.
WRITE: / |Livro "{ mv_titulo }" devolvido.|.
ENDMETHOD.
METHOD get_info.
DATA(lv_status) = COND string( WHEN mv_disponivel = abap_true
THEN 'Disponível'
ELSE 'Emprestado' ).
rv_info = |{ mv_titulo } - { mv_autor } ({ lv_status })|.
ENDMETHOD.
ENDCLASS.
CLASS lcl_biblioteca IMPLEMENTATION.
METHOD adicionar_livro.
APPEND io_livro TO mt_livros.
WRITE: / |Livro adicionado: { io_livro->mv_titulo }|.
ENDMETHOD.
METHOD listar_livros.
WRITE: / 'LIVROS NA BIBLIOTECA:', /.
ULINE.
LOOP AT mt_livros INTO DATA(lo_livro).
WRITE: / lo_livro->get_info( ).
ENDLOOP.
ENDMETHOD.
METHOD buscar_por_isbn.
LOOP AT mt_livros INTO DATA(lo_livro).
IF lo_livro->mv_isbn = iv_isbn.
ro_livro = lo_livro.
EXIT.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
" ============ PROGRAMA PRINCIPAL ============
START-OF-SELECTION.
" Criar biblioteca
DATA(lo_bib) = NEW lcl_biblioteca( ).
" Adicionar livros
lo_bib->adicionar_livro( NEW lcl_livro(
iv_titulo = 'Clean Code'
iv_autor = 'Robert Martin'
iv_isbn = '978-0132350884'
) ).
lo_bib->adicionar_livro( NEW lcl_livro(
iv_titulo = 'Design Patterns'
iv_autor = 'Gang of Four'
iv_isbn = '978-0201633610'
) ).
SKIP.
" Listar livros
lo_bib->listar_livros( ).
SKIP.
" Emprestar livro
DATA(lo_livro) = lo_bib->buscar_por_isbn( '978-0132350884' ).
IF lo_livro IS BOUND.
lo_livro->emprestar( ).
ENDIF.
SKIP.
" Listar novamente
lo_bib->listar_livros( ).
💡 Boas Práticas
| ✅ Fazer | ❌ Evitar |
|---|---|
| Usar nomes descritivos | Abreviaturas confusas |
| Métodos pequenos e focados | Métodos gigantes |
| Encapsular dados (private) | Tudo público |
| Usar NEW quando possível | CREATE OBJECT desnecessário |
| Verificar IS BOUND | Usar objetos sem verificar |
🚀 Próximo Passo
Aprenda sobre Atributos e Métodos em detalhe.