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.
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:
lista1 = [1,2,3.14,'abc',True,[4,5,6]] lista2 = lista1 lista2[-1][0] = 10 print lista1 print lista2
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:
lista2 = lista1[:]
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:
d = {'Marcos':28, 'Maria':34, 'Pedro':18} print(d['Marcos'])
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).
class Pessoa: def __init__(self, nome, idade): self.nome = nome self.idade = idade p = Pessoa('marcos', 28)
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:
> Obj = OBJ_NEW('ObjectClass', PROPERTY = value, ... )
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:
> Obj.PROPERTY = value, ...
ou chamando o método “SetProperty” com sua propriedade-valor:
> Obj.SetProperty, PROPERTY = value, ...
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):
> variable = Obj.PROPERTY > Obj.GetProperty, PROPERTY = variable, ...
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:
> Obj.MYPROPERTY = 1 > Obj.SetProperty, MYPROPERTY = 1 > Obj.SetProperty, /MYPROPERTY
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:
> plotcolor = myPlot.COLOR > myPlot.GetProperty, COLOR = plotcolor
O valor da propriedade “COLOR” é devolvido na variável “plotcolor”. Veja um exemplo de como acessar (definir ou obter) propriedades de objetos aninhados:
> p = PLOT(/TEST, TITLE="My Plot") > ax = p.AXES > ax[3].COLOR= 'red'
No objeto “ax” (um vetor), seu quarto elemento é obtido e “SetProperty, COLOR=’red'” é definido pelo objeto. Veja outro exemplo:
> PRINT, p.TITLE.STRING
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.
One comment