Orientação a Objetos usando Java Patricia A. Jaques Contribuições: Luiz Gonzaga Jr Classes e Objetos • Para entendermos os conceitos de orientação a objetos é necessário entendermos o que é um objeto. Por exemplo, consideremos objetos do mundo real: seu cachorro, seu computador, sua bicicleta. • Os objetos do mundo real tem duas características: eles tem estado e comportamento. Por exemplo, cachorros tem estados (nome, cor, tamanho) e comportamentos (latir, andar, correr). • Objetos de software, assim como, objetos do mundo real possuem estado (variáveis) e comportamento (métodos). Podemos representar objetos do mundo real através de objetos de software (por exemplo, um livro), assim como, também podemos modelar conceitos abstratos (por exemplo, uma ação do usuário em uma interface gráfica). Correntista #Nome:string #Saldo: float +verificaSaldo ( ); +depositaValor ( ); +retiraValor ( ); • Classes: descrevem as informações armazenadas e os serviços providos por um objeto – especificação de objetos • Objetos: cada uma das instâncias de uma classe. – Por exemplo: cada uma das contas vai ser um objeto – existe apenas em tempo de execução?! Definindo uma classe em Java class ContaCorrente { } Definindo uma classe em Java Variáveis: definem o comportamento estático do objeto. Variável de Classe Variáveis de Instância class ContaCorrente { static float montanteTotal; float saldo; String nome; // Definição dos métodos } Definindo uma classe em Java Classe ContaCorrente montanteTotal: 600 Maria João Joana 100 200 300 Definindo uma classe em Java • Métodos: definem os serviços que podem ser solicitados a uma instância (objeto), ou seja, o comportamento dinâmico de um objeto. • Por exemplo, na classe ContaCorrente podem ser definidos os métodos: - verificaSaldo: retorna o saldo da conta corrente; - depositaValor: deposita um valor especificado x na conta; - retiraValor: retira um valor especificado x da conta; • Os métodos determinam o comportamento dos objetos de uma classe. • Quando um método é invocado, se diz que o objeto está recebendo uma mensagem (para executar uma ação). • No jargão da OO, um objeto chamar um método de outro é: – um objeto cliente enviar uma mensagem a um objeto servidor. • Um objeto pode nunca manipular os dados internos de outros objetos. – A manipulação pode ocorrer através de chamada de métodos do objeto que está tendo os valores de seus dados modificados. Definição de Métodos <modificador> <tipo de retorno> <nome> (lista de argumentos) { <bloco de código> } Mutator Methods public void setData (int d, int m, int a) { ... } Acessor Methods public int getDay () { ...} public void exibeData ( ) { System.out.println (d+”/”+m+”/”+a); } Definindo uma classe em Java class ContaCorrente { static float montanteTotal; float saldo; String nome; float verificaSaldo ( ) { return saldo; } void depositaValor (float valor) { saldo = saldo + valor; montanteTotal += valor; } void retiraValor (float valor) { if (saldo>=valor) { saldo = saldo – valor; montanteTotal -= valor; } } } Criando um objeto • Objeto é uma instância de uma classe; • Usamos o operador new para criar um objeto. Variável que conterá uma referência a um objeto ContaCorrente minhaConta; minhaConta = new ContaCorrente ( ); Criação do objeto ContaCorrente minhaConta = new ContaCorrente ( ); Acessando variáveis e métodos de um objeto Operador ponto (.) class AcessaContaCorrente { public static void main (String args [ ]) { ContaCorrente minhaConta = new ContaCorrente ( ); minhaConta.nome = “Maria”; float saldo; Nome: Maria saldo = minhaConta.verificaSaldo ( ); Saldo: Saldo:200 0 minhaConta.depositaValor (200); saldo = minhaConta.verificaSaldo ( ); } } ContaCorrente outraConta = new ContaCorrente ( ); outraConta.nome = “Joao”; Nome: Joao saldo = outraConta.verificaSaldo ( ); Saldo: 0 Exercício 1 – Criando Objeto ContaCorrente • Implemente a classe ContaCorrente da seção 3.1.2 • Implemente um método print() que exiba na tela os dados do dono da conta corrente. • Crie uma outra classse que se chama AcessaContaJoao – No método main(), crie uma conta para o “João da Silva” com saldo = 1000. – Exiba os dados da conta chamando o método print( ). – Faça um saque de 135. – Exiba novamente os dados. Método Construtor • Método que é automaticamente executado ao ser criado o objeto; • É usado para inicialização de variáveis ou para a chamada de outros métodos; • Os métodos construtores tem o mesmo nome que a classe; • Não é obrigatório criar um construtor. Caso não exista a declaração de um construtor, o compilador gera automaticamente um construtor default. • Pode haver mais de um método construtor mas eles tem que ter número de parâmetros diferentes ou tipos de parâmetros diferentes. Método Construtor class ContaCorrente { static float montanteTotal; float saldo; String nome; public ContaCorrente (String nomeDono) { nome = nomeDono; saldo = 0; } float verificaSaldo ( ) { return saldo; } // restante do código } Acessando variáveis e métodos de um objeto Operador ponto (.) class AcessaContaCorrente { public static void main (String args [ ]) { ContaCorrente minhaConta = new ContaCorrente (“Maria”); minhaConta.nome = “Maria”; float saldo; Nome: Maria saldo = minhaConta.verificaSaldo ( ); Saldo: Saldo:200 0 minhaConta.depositaValor (200); saldo = minhaConta.verificaSaldo ( ); } } ContaCorrente outraConta = new ContaCorrente (“Joao”); outraConta.nome = “Joao”; saldo = outraConta.verificaSaldo ( ); Nome: Joao Saldo: 0 Operador this • Java inclui um valor de referência especial, chamado this, que é usado dentro de qualquer método para referir-se ao objeto corrente. • O valor de this refere-se ao objeto do qual o método corrente foi chamado. Operador this class TestaThis { int var1 = 4; public void metodo () { int var1 = 8; System.out.println (var1); } } var1=8; class TestaThis { int var1 = 4; public void metodo () { int var1 = 8; System.out.println (this.var1); } } var1=4; Operador this class ContaCorrente { static float montanteTotal; float saldo; String nome; public ContaCorrente (String nome) { this.nome = nome; saldo = 0; } ... // restante do código } class ContaCorrente Variáveis Estrutura membro { static float montanteTotal; float saldo; String nome; public ContaCorrente (String nome) { this.nome = nome; Método saldo = 0; Construtor } float verificaSaldo ( ) Métodos { return saldo; } void depositaValor (float valor) { saldo = saldo + valor; montanteTotal += valor; } } void retiraValor (float valor) { if (saldo>=valor) { saldo = saldo – valor; montanteTotal -= valor; } } public static void main (String args [ ]) { ContaCorrente minhaConta = new ContaCorrente ("Maria"); minhaConta.depositaValor (200); float saldo = minhaConta.verificaSaldo ( ); System.out.println (saldo); } Método Main Exercício 2 – Classe Pessoa • Implemente a classe Pessoa • Uma pessoa possui: – – – – um nome; uma data de nascimento; um endereço; implemente o método print ( ) : exibe na tela os dados da Pessoa. • No método public static void main : – crie dois objetos do tipo Pessoa: um que represente você e outro que represente o colega do lado. Sobrecarga de Métodos • É possível criar métodos com mesmo nome, mas lista de parâmetros diferentes. • Isto é chamado de sobrecarga de métodos (ou overloading). • É reconhecido em tempo de compilação. • É devido a esta propriedade que podemos ter dois métodos construtores com parâmetros diferentes. Sobrecarga de Métodos class ContaCorrente { static float montanteTotal; float saldo; String nome; public ContaCorrente (String nome) { this.nome = nome; saldo = 0; } public ContaCorrente (String nome, float saldo) { this.nome = nome; this.saldo = saldo; } ... // restante do código } Exercício 2 – Classe Pessoa • Na classe Pessoa • Crie um método construtor que crie um objeto Pessoa recebendo como parâmetro o nome da Pessoa e outro que não receba nada como parâmetro. • No método public static void main : – crie dois objetos do tipo Pessoa: – um que represente você, não passando nada para o método construtor; – outro que represente o colega do lado: passando o nome do colega como parâmetro. Passagem de Parâmetros por Valor • Passagem de Argumentos para Métodos em Java: – Java passa somente argumentos por Valor – O argumento passado para outro método não pode ser alterado • Não há passagem de argumentos por referência – Se um argumento passado for um objeto (instância de uma classe): • as variáveis membros deste objeto poderão ser alteradas; • Mas a referência do próprio objeto não pode ser alterada. Passagem de Parâmetros por Valor class TestaPassagemParametros{ public static void trocaValorPrimitivo (int num){ num = num +6; } public static void trocaValorObjeto (ContaCorrente c) { c.saldo = 300; } public static void trocaReferenciaObjeto (ContaCorrente c){ c = new ContaCorrente ("Mulher Maravilha", 200); } public static void main (String args [ ]) { int val = 11; trocaValorPrimitivo (val); System.out.println ("val = "+val); val=11 ContaCorrente minhaConta = new ContaCorrente ("SuperHomem"); System.out.println (minhaConta.saldo); trocaValorObjeto (minhaConta); System.out.println (minhaConta.saldo); } } trocaReferenciaObjeto (minhaConta); System.out.println (minhaConta.nome); saldo=0 saldo=300 nome=SuperHomem Exercicio • Implemente o exercício anterior, porém tentando passar como parâmetro para um novo método uma String. • Neste método faça a variável String receber a referência para um outro parâmetro. public static void trocaReferenciaString (String str){ str = “azul”; } O que acontece? Por quê? Modificadores de Acesso Modificador Visibilidade private Podem ser acessados somente por métodos da mesma classe. sem modificador Por qualquer classe (inclusive subclasses). protected Por qualquer classe do mesmo pacote e pelas subclasses (que podem estar no mesmo pacote ou em outro pacote). public Podem ser acessados de qualquer classe. do mesmo pacote Encapsulamento class ContaCorrente { private static float montanteTotal; private float saldo; private String nome; public ContaCorrente (String nomeDono) { nome = nomeDono; saldo = 0; } public float verificaSaldo ( ) { return saldo; } public void depositaValor (float valor) { saldo = saldo + valor; montanteTotal += valor; } public void retiraValor (float valor) { if (saldo >= valor) saldo = saldo – valor; montanteTotal -= valor; } public static float obtemTotalBanco ( ) { return montanteTotal; } } Encapsulamento • Vantagem: Quando alterar os tipos dos dados de uma classe não é necessário alterar as classes que acessam essa classe. class Pessoa { public String nome; public String data; } class AcessaPessoa { public static void main (String args [ ]) { Pessoa p = new Pessoa ( ); p.nome = "Patty"; p.data = "4/4/1976"; } } class Pessoa { public String nome; public int dia; public int mes; public int ano; } class AcessaPessoa { public static void main (String args [ ]) { Pessoa p = new Pessoa ( ); p.nome = "Patty"; p.dia = 4; p.mes = 4; p.ano = 4; } } class Pessoa { private String nome; private String data; public setNome (String nome) { this.nome = nome; } public setData (String data) { this.data = data; } public String getNome () { return nome; } public String getData () { return data; } } class AcessaPessoa { public static void main (String args [ ]) { Pessoa p = new Pessoa ( ); p.setNome ("Joao"); p.setData ("3/4/1967"); } } class Pessoa { private String nome; private int dia; private int mes; private int ano; class AcessaPessoa { public static void main (String args [ ]) { Pessoa p = new Pessoa ( ); p.setNome ("Joao"); p.setData ("3/4/1967"); } } public setNome (String nome) { this.nome = nome; } public setData (String data) { int v [] = separaData (data); dia = v[0]; mes = v[1]; ano = v[2]; } public String getNome () { return nome; } public String getData () { String data = dia + "/" + mes + "/" + ano; return data; } } Exercício 3 - Encapsulamento • Agora que você aprendeu o conceito de encapsulamento, encapsule os atributos da classe Pessoa: – Os dados são private e seus valores podem ser acessados e modificado pelos métodos mutator (set...) e acessor (get...); Herança • Chamamos de herança quando novas classes herdam propriedades (dados e métodos) de outras classes existentes. • Esse é um importante recurso da orientação a objetos que permite a reutilização de código. • As classes que herdam as propriedades são chamadas subclasses; • A classe pai é chamada superclasse. class Ponto { int x, y; public Ponto (int x, int y) { this.x = x; this.y = y; } public Ponto ( ) { this (-1, -1); // o this também pode ser usado para chamar // construtores } } public void print ( ) { System.out.print (“\n”+x +", "+ y); } super class Ponto3D extends Ponto { int z; public Ponto3D (int x, int y, int z) { this.x = x; Código igual na Chamando construtor this.y(x, = y; super y); classe e filho dapai classe pai this.z = z; } public Ponto3D ( ) { this (-1, -1, -1); } } class Ponto3D extends Ponto { int z; public Ponto3D (int x, int y, int z) { super (x, y); // chama o construtor Ponto (x, y) this.z = z; } public Ponto3D ( ) { this (-1, -1, -1); } public void printPonto3D ( ) { Chama método print( ) da classe pai print ( ); System.out.print (", "+z); } } class Herança { public static void main (String args [ ]) { Ponto p1 = new Ponto (1,1); Ponto3D p2 = new Ponto3D (2,2,2); 1, 1 p1.print ( ); p2.printPonto3D ( ); } } 2, 2, 2 Exercício 4 - Herança • Implemente a classe Aluno – A classe Aluno é subclasse da classe Pessoa – A classe Aluno, além de conter os dados de uma pessoa, vai ter uma nota e uma turma. – Crie métodos acessor e mutator para os atributos nota e turma. – Escreva um método print2() que chame o método print() da classe pai (Pessoa) que irá exibir nome, data de nasc e endreço do aluno e exiba na tela a nota e a turma do aluno. • No método public static void main: – crie 1 objeto aluno que represente voce como aluno do curso Java. Que nota você se dá? :o) Sobreposição (Overloading) class Ponto3D extends Ponto { int z; public Ponto3D (int x, int y, int z) { super (x, y); // chama o construtor Ponto (x, y) this.z = z; } public Ponto3D ( ) { this (-1, -1, -1); } Chama método print( ) print public void printPonto3D (){ da classe pai super. print ( ); System.out.print (", "+z); } } Polimorfismo class Polimorfismo { public static void main (String args [ ]) { 3, 3, 3 } Ponto p1 = new Ponto (1,1); Ponto3D p2 = new Ponto3D (2,2,2); Ponto p3 = new Ponto3D (3,3,3); p1.print ( ); 1, 1 p2.print ( ); p3.print ( ); 2, 2, 2 } A capacidade de um objeto decidir qual método aplicará para si na hierarquia de heranças é chamada de polimorfismo. A idéia do polimorfismo é que embora a mensagem seja a mesma, os objetos poderão ter comportamentos diferentes. Dinamic Binding Ponto3D p1 = new Ponto3D ( ); Ponto p2 = new Ponto3D ( ); Ponto3D p3 = new Ponto ( ); Ponto p2 = new Ponto3D ( ); Ponto3D p4 = (Ponto3D) p2; Se não usar casting é gerado erro em tempo de compilação • Um método não pode ser menos acessível que o método que ele sobrescreve (na classe pai). class Ponto { private void print ( ) { ... } } class Ponto3D extends Ponto { public void print ( ) { ... } } Exercício 5 – sobreposição • Na classe Aluno (criada no exercício anterior) faça a sobreposição do método print da classe pai (classe Pessoa) , substituindo o método print2( ) . Classes Abstratas • Problema: – Queremos construir um array de Polígonos. – Um polígono pode ser um Retângulo, um Quadrado, uma Elipse ou um Triângulo. E terão dois métodos básicos: area ( ) e circunferencia ( ). – Mas um array só guarda objetos do mesmo tipo? – Solução: criar uma classe abstrata que declare os métodos area() e circunferencia(), mas não os implementando, pois a área de um Triângulo é diferente da área de um Quadrado. Classes Abstratas abstract class Shape { String cor; public abstract double area ( ); public abstract double circunference ( ); public String getType () { Class c = this.getClass(); return c.getName(); } } Enquanto o programa executa, Java mantém o que é chamado de identificação do tipo em tempo de execução (RTTI). Permite saber a qual classe um objeto pertence. Podemos acessar essa informação usando a classe Class. Classes Abstratas class Circle extends Shape { public static final double PI = 3.141592656358979323846; protected double r; public Circle (double r) { this.r = r; } public double getRadius () { return r; } public double area () { return PI*r*r; } public double circunference () { return 2*PI*r; } } // da class Circle class Rectangle extends Shape { protected double w, h; public Rectangle (double w, double h) { this.w = w; this.h = h; } public double getWidth () { return w; } public double getHeight () { return h; } public double area () { return w*h; } public double circunference () { return 2*(w+h); } } // da class Rectangle Classes Abstratas • Apenas métodos podem ser abstratos; • Se uma classe contiver pelo menos um método abstract, ela deve ser declarada como abstract; • Uma classe abstrata não pode ser instanciada. Só podem ser instanciadas as classes filhas que implementarem os métodos abstracts; • Se uma subclasse não implementar os métodos abstracts da classe abstract, ela também será abstract. • Classes abstratas podem ter variáveis e métodos não abstratos, ou seja, implementados. • Métodos abstract não podem ser private, static e final. Classes Abstratas class ClassesAbstratas { public static void main (String args [ ]) { Shape [ ] shapes = new Shape [2]; shapes [0] = new Circle (2); shapes [1] = new Rectangle (1, 3); double totalArea = 0; for (int i=0; i<shapes.length; i++) { System.out.println ("O objeto "+i+ " é um "+shapes [i].getType()); // ou utilizo instanceof //if (shapes [i] instanceof Circle) System.out.println ("É um Circle"); totalArea += shapes[i].area(); } System.out.println ("Área total de todos os objetos é "+totalArea); } } Exercício 7 – Classes Abstratas • Implemente uma classe Hexagono. Essa classe tambem herda propriedades da classe abstrata Shape. O hexagono possui apenas um atributo que o compimento do lado s (Todos os lados tem comprimentos iguais). • Implemente os métodos area e circunference do hexagono: – A area de um hexagono é: 3/2*Math.sqrt(3)*s*s – A circunferência de um hexagono é: 6*s. • Implemente o método main e crie um hexagono de lado s=5. s • Qual é a area e circunferência deste hexagono? • Mostre estas informações na tela. Interfaces • Uma interface não pode possuir nenhuma implementação; • Todos os métodos são abstratos, mesmo que o programador omita o modificador abstract; • Todos os métodos são públicos, mesmo que o modificador public seja omitido; • Todas as variáveis em uma interface são constantes, mesmo que não sejam declaradas como static final; Interfaces interface MinhaInterface { int getSize ( ); void setSize (int param); } class MinhaClasse implements MinhaInterface { int size; Não é possível criar uma public int getSize ( ) { instância de uma interface. return size; Para criar uma instância } public void setSize (int tam) { é preciso implementar a size = tam; interface. } } Interfaces • Java não permite herança múltipla, por isso uma classe pode ser subclasse(extends) apenas de uma superclasse mas implementar (implements) várias interfaces. • Podemos declarar classe abstrata Shape como interface: – retirar implementação do método Type(); – as classes que implementam Shape podem herdar propriedades de outra classes. Garbage Collection String str = “Primeiro espaço”; System.out.println (“Usando memória original: “+str); str = “Outro espaço”; System.out.println (“Usando outro espaço de memória: “+str); Primeiro espaço str 10 Área de memória liberada pelo Garbage Collection 10 100 Outro espaço 100 Exercício 6 - Agregação • • Implemente a classe Ponto. Um ponto tem dois atributos do tipo inteiro: Ponto – As coordenadas x e y. • Além disso, um ponto também tem os métodos: – Método construtor: • Inicializa as coordenadas x e y com os valores passados como parametro para o método. – setaCoordenadas (int x, int y): • que recebe como parametro os novos valores das coordenadas. – exibe (): TestaReta Reta • Que exibe os valores dos atributos x e y. • • Implemente a classe Reta. Uma Reta possui 2 atributos do tipo Ponto: – O ponto inicial e o ponto final da Reta. • Uma Reta possui os métodos: – Método Construtor: recebe 4 valores inteiros e inicializa as coordenadas x e y de cada ponto. – exibe( ): exibe as coordenadas x e y de cada ponto. • Implemente a classe TestaReta: – que possui apenas o método main. Dentro do método main: • crie uma reta e inicialize o Ponto Inicial com x=2, y = 3 e o Ponto Final com x=5, y=6. • chame o método exobe da classe Reta.