Orientação a Objetos – PROTECTED é mesmo protegido?

Se você leu o título deste post e acha que vamos falar de herança em orientação a objetos, você está enganado. Vamos desafiar seu entendimento de visibilidade de dados em orientação a objetos. Será que o que você sabe realmente é a verdade? Eu decidi escrever este post depois que vi que o que eu entendia sobre o assunto estava errado. Por que não ler isso você também?

protected featured image

Exemplo de Aplicação de MM orientado a objetos

As regras que determinam o conceito de orientação a objetos são algumas mas todas simples: classes, métodos, atributos, eventos, objetos, referências, interfaces, herança, visibilidade e praticamente nada mais. Todavia o que torna orientação a objetos tão desafiador são as inúmeras possibilidades de se resolver um problema com elegância, ou com nem tanta. Isso faz com que sempre haja espaço para novos aprendizados. Veja um exemplo de aplicação de MM abaixo.

Visibilidade de dados

Mesmo que você só tenha lido alguns exemplos de orientação a objetos sabe o conceito de visibilidade de dados. É possível “esconder” dados (atributos) e funcionalidades (métodos) do “mundo externo” (outras classes) usando as sessões PROTECTED e PRIVATE (na sintaxe do ABAP). A diferença entre os dois acaba sendo que:

Tudo o que é PROTECTED  de uma classe pode ser acessado de outras classes, desde que estas sejam classes filhas da primeira.

Veja a nova classe lcl_material_finished abaixo.

Instanciação

Vale a pena relembrar do conceito de instanciação. Uma classe dá forma a algo que pode ser criado diversas vezes. Cada uma destas criações são chamadas de objetos e por possuírem  a mesma forma possuem os mesmos atributos e métodos. Todavia por serem criações independentes, seus dados podem perfeitamente ser diferentes uns dos outros. A instanciação é o processo de criação de um objeto, fator que traz a enorme vantagem de independência de dados a orientação a objetos. START-OF-SELECTION.

Injeção de Dependência

Dependence Injection na minha opinião este é um termo que soa muito mais difícil do que ele realmente é. Caso um objeto precise da ajuda de outro objeto para realizar alguma ação, então uma referência ao segundo objeto pode ser usada como parâmetro de um método do primeiro. Obviamente, você deve estar imaginando que o primeiro objeto só pode pedir ajuda para o segundo objeto acessando seus componentes (atributos ou métodos) públicos, pois classes diferentes fazem parte do “mundo externo” uma da outra.

Misturando todos estes conceitos

O desafio é simples: O que acontece com componentes protegido de um objeto quando tentamos acessá-lo a partir de um outro objeto da mesma classe?

Difícil entender? Veja o código abaixo para simplificar a questão. Estude cada uma das chamadas de métodos e talvez você se surpreenderá com o resultado.

Saída:

protected output

 Refinando o conceito de PROTECTED

Como pode perceber pelo código acima, dados protegidos nem sempre estão protegidos assim. Por isso, vamos refinar a definição de dados e métodos protegidos dada anteriormente.

Tudo o que é PROTECTED  de uma classe pode ser acessado de outras classes, desde que estas sejam classes filhas da primeira. Isso significa que dados protegidos de um objeto SÃO PÚBLICOS para outros objetos da mesma classe ou de classes filhas.

Update 21/Janeiro/2014 – Como apontou o Custódio em comentários, o mesmo vale para componentes protegidos.

Talvez você pense que isso é uma falha do ABAP, mas se testar o mesmo exemplos em outras linguagens como Java terá exatamente o mesmo resultado.

Fonte

Disse no começo deste post que decidi escrever este post quando percebi que o que entendia não era exatamente a verdade. Eu refinei meu conceito de orientação a objetos pesquisando perguntas para responder na SCN e achei a thread “Why is this possible in ABAP Objects?“. Está aí mais um exemplo de tantos outros que provam porque é importante participar da SCN. Logo esta é mais uma prova que se você não tem cadastro na SCN ou simplesmente não participa, é um profissional SAP totalmente limitado pelo seu tempo de estudo e experiência.

Existem até outras formas de se “burlar” o conceito de PROTECTED, esta eu encontrei somente no processo de revisão deste post.

Qual era seu conceito de PROTECTED?

Agora que estudou o código de exemplo, responda: “Você melhorou o conceito que tinha sobre PROTECTED?”. Comente abaixo a resposta.

  1. Li o post e os comentários no SCN. Eu tb achava que o controle era por instância, e não pela classe… Interessante que isso se replica em outras linguagens, então aposto que muita gente deve ter esse conceito de que protected vale por instância.

    Procurei um site onde eu estudava C++ para dar uma olhada, e o cara também explica direitinho: http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/ “Private members can only be accessed by member functions of the same class.”. Em momento nenhum ele fala de instância!

    Impressionante como um entendimento errado/incompleto afeta tudo que a gente lê depois sobre o tema. Ainda bem que agora sabemos a verdade! 🙂

    Valeu por compartilhar Fábio!

    • Tem toda razão Maurício. E mesmo sem dizer “instância” em nenhum momento eu anteriormente já associava aos objetos pois ora, eles são independentes – na maioria dos casos.

      Fica ainda mais fácil de fazer besteira caso não se crie classes com responsabilidades distintas (como a classe ‘writer’ no exemplo do post).

      Obrigado por compartilhar o link do C++!

      Abraços,

    • Caraca! Eu nem sabia que dava para definir text symbols em classes. Geralmente minhas classes com ALV são locais e acabo usando os do programa mesmo. Aprendi mais uma coisa. Obrigado Fawcs!

      Abraços!

  2. Fala Fabio,

    Acopanhei a discussao ontem na SCN e pra ser bem sincero achei que tava todo mundo falando um monte de abobrinha. Mas esse seu post me ajudou a entender o problema. Voce pode aproveitar o post e mudar sua definicao de PRIVATE, pois o mesmo se aplica nesse caso. Mudei o attributo v_volum de PROTECTED para PRIVATE e seu programa continua funcionando exatamente igual. Claro, porque a visibilidade PRIVATE segue o mesmo conceito de PROTECTED: por classe, nao por instancia.

    Abraco,
    Custodio

    • Oi Custodio! Várias mitos comentando neste post!

      Fico feliz que tenha ajudado. Para ser sincero este post na SCN soa como uma pergunta bem básica mas na verdade é algo que considero avançado dentro de orientação a objetos. Só fui perceber o problema depois da alguns comentários com código.

      Sim, você tem toda a razão no que disse: vale a mesma regra para componentes privados – eles são públicos para objetos da mesma classe.

      Abraços!

  3. Hoje me deu uma idéia, e se eu acessar a referencia da variavel privada?.
    O ABAP não só deixa você retornar a referencia do atributo privado, como também deixa você manipular essa variavél do lado de fora!.

    Bom, segue a brincadeira!

    REPORT zfaw_test_reference.

    CLASS lcl_teste DEFINITION.
    PUBLIC SECTION.
    METHODS:
    get_priv EXPORTING ex_priv TYPE char1,
    get_priv_by_ref EXPORTING data TYPE REF TO data.
    PRIVATE SECTION.
    DATA: priv TYPE char1 VALUE ‘2’.
    ENDCLASS.

    CLASS lcl_teste IMPLEMENTATION.
    METHOD get_priv.
    ex_priv = priv.
    ENDMETHOD.
    METHOD get_priv_by_ref.
    GET REFERENCE OF me->priv INTO data.
    ENDMETHOD.
    ENDCLASS.

    DATA: obj TYPE REF TO lcl_teste,
    data_ref TYPE REF TO data,
    char TYPE char1.
    FIELD-SYMBOLS: TYPE any.

    START-OF-SELECTION.

    BREAK-POINT.

    CREATE OBJECT obj.

    obj->get_priv(
    IMPORTING
    ex_priv = char ).
    WRITE: / ‘Before get by reference: ‘ , char.

    obj->get_priv_by_ref( IMPORTING data = data_ref ).

    ASSIGN data_ref->* TO .

    = 3.

    obj->get_priv(
    IMPORTING
    ex_priv = char ).

    WRITE: / ‘After get by reference: ‘ , char.