Programação Orientada a Objetos mleal@inf.puc-rio.br 1 Histórico O conceito de Classe foi introduzido na década de 60 através da LP Simula 67. A primeira LP OO pura foi Smalltalk desenvolvida durante a década de 70. Outros exemplos de LPs OO são Eiffel, Java, Object Pascal e C#. LPs como C++, Ada e Perl suportam o conceito de classe mas não são consideradas LPs OO em um sentido mais rigoroso. mleal@inf.puc-rio.br 2
Introdução Com o desenvolvimento de aplicações de software cada vez mais complexas, cresceram as demandas por metodologias que pudessem abstrair e modularizar as estruturas básicas de programas. A programação OO suporta a abstração e mudularização através da especificação de tipos abstratos de dados (as classe), e promove a reutilização de software por meio do mecanismos de herança. mleal@inf.puc-rio.br 3 Introdução A programação OO busca modelar aplicações seguindo uma estrutura semelhante àquela encontrada no mundo real. O mundo é composto por objetos que apresentam estados e comportamentos. Um gato por exemplo tem um nome, uma cor e uma raça (os estados) e ele come, mia e caça ratos (os comportamentos). mleal@inf.puc-rio.br 4
Modelo OO Uma aplicação OO é composta por diferentes objetos e uma sequência de ações (interações). Uma ação se inicia através do envio de uma mensagem para um agente (um objeto) que será responsável por tratar essa ação. A mensagem carrega uma requisição, além de toda a informação necessária (argumentos) para que a ação seja executada. Se o agente receptor da mensagem a aceita, ele tem a responsabilidade de executar um método para cumprir a requisição. mleal@inf.puc-rio.br 5 Objetos Constituem as estruturas básicas de uma aplicação. Estão preparados para cumprir um determinado conjunto de requisições. Recebem essas requisições através de mensagens. Possuem a responsabilidade de executar um método que cumpra a requisição. Possuem um estado representado por informações internas. mleal@inf.puc-rio.br 6
Atributos, Métodos e Mensagens Um objeto é composto por atributos e métodos. O estado de um objeto é representado por variáveis denominadas atributos. Alterações no estado de um objeto geralmente ocorrem através da invocação de seus métodos. Métodos são as rotinas que descrevem os possíveis comportamentos ou ações de um objeto. Um método de um objeto é invocadodo através do envio, ao objeto, de uma mensagem apropriada mleal@inf.puc-rio.br 7 Interface (Protocolo) Parte privada do objeto (visão interna) Métodos usados internamente e atributos Parte compartilhada do objeto (interface ou protocolo) Métodos que podem ser invocados externamente Corresponde às mensagens que um objeto é capaz de responder Especifica portanto um contrato quais as operações que o objeto pode e deve realizar Não contém qualquer informação sobre como as operações devem ser executadas ou implementadas mleal@inf.puc-rio.br 8
Encapsulamento Princípio aplicado a programação OO visando garantir a abstração dos dados (esconde( os detalhes da implementação). Um objeto não deve permitir que nenhum outro objeto acesse seus dados diretamente. O relacionamento entre objetos deve ocorrer preferencialmente a partir de métodos públicos (interface). Caso haja uma mudança na implementação da classe,, o relacionamento entre os objetos não será afetado. mleal@inf.puc-rio.br 9 Classes Especificam que informações um objeto irá armazenar (os atributos), e o conjunto de requisições que um objeto pode cumprir (os métodos). Encapsulam a implementação dos métodos. Definem a interface de um objeto. Objetos são instâncias de classes. Classes podem ser compostas em hierarquias, através de herança. mleal@inf.puc-rio.br 10
Exemplo - Java atributos interface class Produto { private String nome; private float preco; private void calcmargem(float p) (){ public String getnome(){ métodos public void setnome(string n) (){ public float getpreco() (){ mleal@inf.puc-rio.br 11 Figura Polígono Elipse Triângulo Retângulo uma classe meu_triangulo retangulo2 um objeto mleal@inf.puc-rio.br 12
Exemplo - Object Pascal type Figura=class private BaseX,BaseY: integer; Visible: boolean; public constructor Cons(bx,by: integer); destructor Destroi; interface procedure Desenha(cor: integer); virtual; procedure Apaga; procedure Move(dx,dy: integer) end; mleal@inf.puc-rio.br 13 Herança Permite a definição de classes específicas (subclasses) a partir de classes gerais (superclasses). Subclasses herdam todos os atributos e métodos da superclasse. Subclasses podem declarar novos métodos e atributos ou mesmo redeclarar métodos definidos pela superclasse (sobreescrever - overriding). mleal@inf.puc-rio.br 14
Exemplo C++ class Poligono { protected: int altura, largura; public: void set_valor (int a, int b) { largura=a; altura=b; ; class Retangulo: public Poligono { public: int area (void) { return (altura * largura); ; int main () { Retangulo ret; ret.set_valor(4,3); um objeto uma mensagem mleal@inf.puc-rio.br 15 Herança Quando uma classe B herda de A,, diz-se que B é uma sub- classe de A,, e A é a superclasse de B. B No exemplo anterior Retângulo é uma subclasse de Polígono, e Polígono é a superclasse de Retângulo. Uma subclasse especializa uma superclasse quando redefine métodos, sem ampliar sua interface. Uma subclasse estende uma superclasse quando amplia a sua interface, declarando novos métodos, mas sem redefinir os métodos herdados. Uma subclasse pode ao mesmo tempo estender e especializar uma superclasse. mleal@inf.puc-rio.br 16
Herança de Interface Em algumas LPs é possível distinguir entre herança de implementação e herança de interface. Na herança de interface uma classe herda uma ou mais interfaces. As interfaces estabelecem os métodos (e as respectivas assinaturas) que devem ser implementados pela classe, mas a implementação deve ser integralmente especificada pela subclasse. A herança de implementação usualmente implica na herança de interface. mleal@inf.puc-rio.br 17 Exemplo - Java public interface Relogio { Date getdata(); Time gethora(); void setdata(date d); void sethora(time t); uma interface public Class RelogioDigital implements Relogio{ Date getdata(){ Time gethora(){ void setdata(date d){ void sethora(time t){ void setalarme(int size){ void Display(){ uma classe que herda e implementa a interface mleal@inf.puc-rio.br 18
Herança de Interface A herança de interface é utilizada quando é preciso garantir que uma determinada classe seja capaz de tratar um conjunto particular de mensagens. A implementação das mensagens é específica de cada classe, e não faz sentido a reutilização de código. Um exemplo comum é a interface Runnable: interface Runnable { void run(); mleal@inf.puc-rio.br 19 Herança Múltipla Em algumas situações pode ser interessante definir uma classe a partir de propriedades de duas ou mais classes distintas. Algumas LPs (C++, Eiffel, Smalltalk) suportam este tipo de estrutura através do mecanismo de herança múltipla. mleal@inf.puc-rio.br 20
Exemplo C++ class square{int side; public: int area(){return side * side; ; class color{ char *color_name; public: char *get_color(){return color_name; ; class colored_square: public color, public square{ ; int main () { colored_square s; x = s.get_color(); y = s.area(); mleal@inf.puc-rio.br 21 Anomalia de Herança O mecanismo de herança múltipla introduz um problema conhecido como anomalia de herança. O que acontence com a subclasse se duas super-classes contém métodos com a mesma assinatura? Animais Mamíferos Aquáticos Baleia mleal@inf.puc-rio.br 22
Relacionamentos Uma aplicação OO é estruturada através da especificação de classes e objetos, e dos relacionamentos entre estes. A relação de herança por exemplo é usada para obter o efeito de especialização entre classes. Caminhão é uma especialização de veículo. A relação inversa de especialização é a generalização (veículo é uma generalização de caminhão). mleal@inf.puc-rio.br 23 Relacionamentos Outros exemplos de relacionamento entre classes são: Composição ou agregação; Associação; Uso. mleal@inf.puc-rio.br 24
Composição Neste caso podemos definir uma classe como sendo composta por objetos de outras classes. Não é necessário nenhuma construção especial para suportar composições, basta declarar as classes componentes como atributos da classe composta. mleal@inf.puc-rio.br 25 Exemplo Carro Motor Chassi class carro { Motor motor; Chassi chassi; atributos mleal@inf.puc-rio.br 26
Uso Ocorre quando as instâncias de uma classe usam os serviços oferecidos por instâncias de outra classe. No exemplo abaixo, Motorista usa os serviços acelera() e freia() de Veículo. Motorista dirigir() Veiculo motor cambio acelera() freia() mleal@inf.puc-rio.br 27 Associação Ocorre quando um objeto faz referência a um objeto de outra classe. No exemplo abaixo, um Motorista está associado a um Veículo. Motorista nome endereço veículo Veículo mleal@inf.puc-rio.br 28
Polimorfismo Polimorfismo é a capacidade de um objeto tomar diversas formas. polimorfismo universal adhoc paramétrico subtipo sobrecarga coerção mleal@inf.puc-rio.br 29 Coerção e Sobrecarga Em LPs com coerção um tipo pode ser transformado em outro dependendo do contexto: int x =5; float y = 3.5*x; No caso de sobrecarga, um mesmo nome denota funções diferentes também conforme o contexto: String s = João + Silva ; int x = 4 + 5; mleal@inf.puc-rio.br 30
Polimorfismo Paramétrico O comportamento de uma estrutura qualquer depende de uma parâmetro que indica o tipo de dado a ser tratado: Class stack [T] variable lst : List[T] := new List[T] method push(x:t) returns nothing lst := lst.prepend(x) method pop() returns T variable tmp : T := lst.head() lst := lst.tail() return tmp method top() returns T return lst.head() method empty?() returns Boolean returns lst.empty?() mleal@inf.puc-rio.br 31 Polimorfismo de Subtipo Este é o polimorfismo mais comum em LPs OO, e é o tipo ao qual geralmente nos referimos quando utilizamos o termo polimorfismo. Quando declaramos uma variável como sendo de uma classe específica, ela pode conter instâncias de quaisquer subclasses desta classe específica. Como a interpretação de uma mensagem é da responsabilidade do objeto que a recebe, uma mesma mensagem pode ser interpretada de forma diferente dependendo do objeto que a recebe. A definição do método que irá ser executado como resultado do envio de uma mensagem geralmente só acontece em tempo de execução (late( late-binding). mleal@inf.puc-rio.br 32
Exemplo Animal a; a = new Cachorro(); a.falar(); au! au! a = new Gato(); a.falar(); miau! miau! a = new Galinha(); a.falar(); cocorocó! mleal@inf.puc-rio.br 33 Typecast Para acessar um método específico de uma subclasse é necessário fazer um typecast da variável declarada como da superclasse. Exemplo: Animal a; a = new Galinha(); ((Galinha)a).botar_ovo; a = new Cachorro(); ((Galinha)a).botar_ovo; erro mleal@inf.puc-rio.br 34
Classes Abstratas Na hierarquia abaixo, a classe Figura existe apenas para dar origem às classes Polígono e Círculo.. Não podem ser criadas instâncias dessa classe já que sua especificação é imcompleta. Figura Polígono Círculo Classes abstratas são classes para as quais não podem ser criadas instâncias. Elas existem na hierarquia de classes apenas para definir a interface de subclasses. mleal@inf.puc-rio.br 35 Exemplo C++ class Figura { public: virtual float get_area() = 0; virtual float get_perimetro = 0; ; class Circulo::Figura { public: float get_area(){ return 3.14*raio*raio; float get_perimetro{ return 6,28*raio; ; mleal@inf.puc-rio.br 36
Métodos Virtuais ou Abstratos Quando apenas a assinatura de um método é declarada por uma classe este método é denominado virtual ou abstrato. Classes abstratas devem ter pelo menos um método virtual. Em C++ apenas os métodos declarados como virtuais são vinculados dinamicamente (late- binding). Em Java todos os métodos são vinculados dinamicamente. mleal@inf.puc-rio.br 37 Late Binding em C++ Para implementar o late binding de métodos, o compilador C++ cria uma tabela denominda VTABLE para todas as classes que contém métodos virtuais. A VTABLE armazena o endereço dos métodos virtuais. Adicionalmente, para todas as classes com métodos virtuais é criado um atributo denominado vpointer (VPTR) que aponta para a VTABLE do objeto. Quando um método é invocado, a VTABLE do objeto é utilizada para descobrir o endereço do método especívifo que deve ser executado. mleal@inf.puc-rio.br 38
Late Binding em C++ Animal a[3]; a[0] = new Gato(); a[1] = new Cachorro(); a[2] = new Galinha(); array de Animal instância de Gato vptr instância de Cachorro vptr instância de Galinha vptr VTABLEs &Gato:: falar &Gato:: comer &Cachorro:: falar &Cachorro:: comer &Galinha:: falar &Galinha:: comer mleal@inf.puc-rio.br 39 Construtores e Destrutores A instanciação de um objeto usualmente acontece através da invocação de um método especial conhecido como construtor. O construtor é responsável por inicializar adequadamento o objeto. Algumas LPs OO suportam também o conceito de destrutores, métodos que são executados antes de um objeto ser destruído (desalocado da memória). mleal@inf.puc-rio.br 40
Exemplo class Date { private: int day; int month; int year; public: // Construtor Date(int d, int m, int y) { set(d, m, y); // Destrutor ~Date(){ void set(int d, int m, int y); ; mleal@inf.puc-rio.br 41 Sobrecarga em LPs OO Em programação OO é bastante comum a definição de métodos sobrecarregados. Um exemplo de aplicação é na definição de construtores. O método associado a uma invocação pode ser determinado a partir da análise léxica (estática) do código (desde que não haja a possibilidade de polimorfismo). mleal@inf.puc-rio.br 42
Exemplo class Date { private: int day, month, year; public: // Construtor 1 Date(int d, int m, int y) { set(d, m, y); // Construtor 2 Date() { set(1, 1, 2000); ; int main () { Date d(); // Construtor 1 mleal@inf.puc-rio.br 43 Atributos de Classes e Métodos Estáticos Em algumas LPs OO pode-se definir atributos associados diretamente a uma classe. Os atributos de uma classe podem ser manipulados apenas por métodos estáticos métodos que também são associados a uma classe. Atributos de classe são equivalentes a variáveis globais de LPs não OO, e métodos estáticos equivalem a funções ordinárias. mleal@inf.puc-rio.br 44
Exemplos public class Math{ private static double pi = 3.14; public static double getpi(){ return pi; public class Teste{ private static int instances = 0; public Test(){ ++instances; mleal@inf.puc-rio.br 45