Orientação a objeto no python e IDL

Em ciência da computação, o paradigma “orientação a objeto” tem bases conceituais e origem no campo de estudo da cognição (ato ou processo da aquisição do conhecimento que se dá através da percepção, raciocínio, memória, linguagem, etc), que influenciou a área de inteligência artificial e da linguística, no campo da abstração de conceitos do mundo real. Na programação orientada a objetos, implementa-se um conjunto de classes que definem os objetos presentes no sistema de software.

Resumo conceitual de orientação a objeto. Texto adaptado de Blog Etílico
Resumo conceitual de orientação a objeto. Texto adaptado de Blog Etílico.

Um objeto é uma entidade do mundo real (uma referência a um local da memória que possui um valor), cada um com uma identidade – ou seja, dois objetos são distintos mesmo que eles apresentem exatamente as mesmas caraterísticas. A identificação do objeto deve ser única, uniforme e independente do seu conteúdo. Esse objeto pode ser uma variável (capaz de reter e representar um valor ou expressão), função (porção de código que resolve um problema específico) ou estrutura de dados (modo particular de armazenamento e organização de dados).

A estrutura de um objeto é representada em termos de atributos (propriedades). Podem ser divididos em atributos de instância (seus valores determinam o estado de cada objeto) ou atributos de classe (estado que é compartilhado por todos os objetos de uma classe). O comportamento de um objeto é representado pelo conjunto de operações que podem ser executadas sobre o objeto – quando possuem a mesma estrutura e o mesmo comportamento são agrupados em classes.

A classe é uma abstração que descreve propriedades importantes para uma aplicação de um conjunto de objetos individuais. Cada objeto é uma instância dessa classe, ou seja, sua concretização – uma classe é como um “molde” que gera instâncias de um certo tipo; um objeto é algo que existe fisicamente e que foi “moldado” na classe. Portanto, cada classe determina o comportamento (definido nos métodos, ou seja, as habilidades e ações possíveis) e estados possíveis (atributos) de seus objetos, assim como o relacionamento com outros objetos.

Um método é a implementação de uma operação para uma certa classe. A mesma operação pode se comportar de forma diferente em classes diferentes e pode ser implementada por mais de um método: isso é chamado polimorfismo. O objeto possui atributos e os métodos que determinam o seu “comportamento” (explicitado pelas interfaces).

Herança é o mecanismo que permite compartilhar atributos e operações entre classes baseada em um relacionamento hierárquico. Uma classe pode ser definida de forma genérica e depois refinada sucessivamente em subclasses, onde cada subclasse incorpora (herda) todas as propriedades de sua classe base e adiciona suas propriedades únicas e particulares.

Aplicação dos conceitos na linguagem python

Veja essa sequência de comandos em python a partir da definição de uma lista com elementos inteiros, ponto flutuante, string, booleano e outra lista. O objetivo é criar uma segunda lista igual à primeira e substituir o primeiro elemento da “lista dentro da lista”, mas mantendo a lista original intacta:

Se não fosse linguagem orientada a objeto, realmente a variável lista2 receberia o conteúdo de lista1 e a alteração do primeiro elemento de lista2 teria ocorrido, e não em lista1. No entanto, em python, tudo são objetos, inclusive uma lista; lista1 e lista2 são apenas rótulos que apontam para o objeto “[1,2,3.14,’abc’,True,[4,5,6]]”. Para conferir isso, basta executar o comando print(id(lista1) == id(lista2)) e verificar que é impresso o booleano True (ou seja, a id é a mesma).

Quando é atribuído um objeto a outro, apenas se está copiando a referência à lista, e não seu conteúdo. Nesse caso, lista2 funciona como um apelido de lista1. Para copiar o conteúdo (usando outro espaço na memória), deve-se alterar a atribuição da segunda linha pelo seguinte comando:

Uma lista (“list”) é um objeto mutável: seu estado pode ser modificado após ser criado. Já uma tupla (“tuple”) é um objeto imutável, ou seja, se tentar mudar algum elemento, resultará em erro. Além disso, a diferença com relação à lista é que sua atribuição de elementos usa parênteses () em vez de colchetes []. Um conjunto (onde a ordem não interfere – não suporta indexificação – e não são admitidos elementos repetidos) possui os elementos separados por vírgulas dentro de chaves {}.

Por fim, um dicionário também é um objeto mutável, mas com propriedades de acesso diferentes. É composto por um conjunto de chaves e valores: se quer um valor, pergunta pela chave. Por exemplo, um dicionário onde as chaves (“keys”) sejam os nomes de pessoas e os valores (“values”) são as idades delas:

A segunda linha imprime a idade de Marcos. As chaves que são usadas como os índices da lista. No entanto, se a chave não existir, ela será adicionada ao dicionário, diferentemente do que acontece na lista, que diz que o índice não existe (fora do range do vetor).

Veja esse exemplo da classe “Pessoa” definida em python, com funções associadas a elas (chamadas então de métodos). Ela usa o método init (o duplo underline é chamado de “Dunder”, de “Double UNDERscore”); primeiro parâmetro sempre é self (por definição), que pode ser entendido como uma referência ao objeto em si recém-criado que precisa ser iniciado (utilizado para acessar qualquer atributo da instância). No caso, init é um construtor que associa um rótulo ao objeto. Na última linha, existe uma instância passando alguns atributos (p.nome e p.idade).

A palavra class é executada pelo interpretador quando encontrada no código, e o resultado dessa execução é um novo objeto existente no escopo do módulo. Ou seja, class é um construtor de objetos do tipo “type”. Já a palavra def também cria objetos do tipo “function”. Os métodos/funções também são atributos. Veja mais sobre Python clicando no link.

Aplicação dos conceitos na linguagem IDL

Na linguagem IDL, os objetos (ou entidades) tem propriedades associadas a ele, como “color”, “line style”, “size”, etc. Por exemplo, você pode definir as propriedades na inicialização de um objeto da seguinte forma utilizando o par propriedade-valor:

Se o objeto herda da classe IDL_Object, você pode definir ou alterar as propriedades do objeto após sua inicialização chamando diretamente a propriedade utilizando o operador ponto:

ou chamando o método “SetProperty” com sua propriedade-valor:

onde “PROPERTY” é o nome da propriedade do objeto e “value” é o valor associado da propriedade. Se o objeto herda da classe IDL_Object, você pode recuperar os valores da propriedade chamando-a diretamente com o operador ponto (linha de cima) ou chamando o método “SetProperty” com sua propriedade-valor (linha de baixo):

Obs: os pares propriedade-valor tem o mesmo comportamento que os pares chave-valor, ou seja, você pode definir o valor de uma propriedade booleana como 1 precedendo o nome da propriedade com um caractere de barra “/”. Veja as formas equivalentes:

Para obter o valor de uma propriedade, você pode usar o operador ponto (se o objeto herda de IDL_Object) ou chamar o método GetProperty do objeto. Veja o exemplo:

O valor da propriedade “COLOR” é devolvido na variável “plotcolor”. Veja um exemplo de como acessar (definir ou obter) propriedades de objetos aninhados:

No objeto “ax” (um vetor), seu quarto elemento é obtido e “SetProperty, COLOR=’red'” é definido pelo objeto. Veja outro exemplo:

Para o objeto p, GetProperty é chamada para obter o objeto “TITLE”, e então GetProperty é chamada no objeto título para obter o valor da string do título.

Ao acessar métodos e propriedades de uma classe, você pode usar o operador seta (->), com a seguinte sintaxe: Objeto->[Classe::]Método [, PROPRIEDADE=variável]

Abstração e encapsulação

As duas ações são importantes para o desenvolvimento de sistemas. Abstração consiste de focalizar nos aspectos essenciais inerentes a uma entidade (concentrar no que o objeto é e faz) antes de se decidir como ele será implementado. A encapsulação consiste em separar os aspectos externos de um objeto (acessíveis a outros objetos) dos detalhes internos de implementação do objeto (escondidos dos outros objetos), o que evita as partes de um programa tornarem-se tão interdependentes que uma pequena mudança tenha grandes efeitos colaterais.

Fontes

Wikipedia, UNICAMP, Exelis e Blog Etílico.