Algoritmos e Programação II Baseado no Material do Prof. Júlio Machado Sobrecarga Em várias linguagens é comum encontrarmos rotinas que fazem basicamente a mesma coisa, porém, têm nomes distintos porque se diferenciam nos tipos dos parâmetros. Ex.: classe Acumulador Dois métodos adicionadouble e adicionaint. Ambos somam o valor recebido como parâmetro ao atributo de instância. public class Acumulador { private double valor; public Acumulador() { valor = 0; public double getvalor() { return(valor); public void adicionadouble(double n) { valor = valor + n; public void adicionaint(int n) { valor = valor + n; 1
Acumulador - valor: double + Acumulador ( ) + getvalor ( ): double + adicionadouble (n: double) + adicionaint (n: int) Programador necessita conhecer o nome de vários métodos que fazem a mesma tarefa! adicionadouble(3.1) valor = 1.5 valor = 4.6 adicionaint(2) valor = 1.5 valor = 3.5 Em Java, podemos criar os dois métodos com o mesmo nome! A condição é que tenham uma lista de parâmetros diferentes. public class Acumulador { public void adiciona(double n) { valor = valor + n; public void adiciona(int n) { valor = valor + n; Acumulador - valor: double + Acumulador ( ) + getvalor ( ): double + adiciona (n: double) + adiciona (n: int) Programador só necessita saber agora que a classe oferece a funcionalidade de adicionar valores de diversos tipos. adiciona(3.1) valor = 1.5 valor = 4.6 adiciona(2) valor = 1.5 valor = 3.5 2
Chama-se de sobrecarga de métodos (overloading) o ato de criar diversos métodos com o mesmo nome que se diferenciam pela lista de argumentos (parâmetros). Métodos são identificados pela sua assinatura: nome do método + lista de parâmetros. Métodos com mesmo nome, mas com tipo, quantidade ou ordenação de parâmetros diferentes, são considerados métodos diferentes. Cuidado!!! Esses métodos possuem uma definição correta para sobrecarga? public void soma(int n, double d) public void soma(double d, int n) ok public void soma(int n) public void soma(int v) public void soma(int n) public double soma(int n) Na API de Java, diversas classes utilizam a sobrecarga de métodos, por exemplo: Classe String valueof (boolean b) valueof (char c) valueof (double d) valueof (float f) valueof (int i) valueof (long l) retorna a representação em String do argumento recebido. 3
Classe Vector add(int indice, Object elemento) insere o elemento na posição indicada do vetor add(object elemento) insere o elemento no final do vetor remove(int indice) remove o elemento da posição indicada do vetor remove(object elemento) busca e remove a primeira ocorrência do elemento encontrada no vetor Sobrecarga de Construtores Usualmente é útil para uma classe possuir mais de um construtor a fim de oferecer diversas maneiras para instanciar e inicializar os objetos dessa classe. Um construtor também pode sofrer o processo de sobrecarga. Exemplo: classe Circulo Deseja-se ter a capacidade de inicializar os atributos de um novo objeto de duas formas: através de um construtor sem parâmetros, que cria um círculo padrão de centro (0,0) e raio 1, e através de um construtor que recebe as informações de centro e raio para criar o círculo. Circulo -centrox:int -centroy:int -raio:int +Circulo(x:int, y:int, r:int) +Circulo() +area():double +circunferencia():double +diametro():int 4
public class Circulo { private int centrox; private int centroy; private int raio; public Circulo(int x, int y, int r){ if (x >= 0) centrox = x; else centrox = 0; if (y >= 0) centroy = y; else centroy = 0; if (r > 0) raio = r; else raio = 1; public Circulo() { centrox = 0; centroy = 0; raio = 1; Testando a classe: public class TesteCirculo { public static void main (String args[]) { Circulo circ1 = new Circulo(); Circulo circ2 = new Circulo(1,2,4); System.out.println("Area circ1= " + circ1.area()); System.out.println("Area circ2= " + circ2.area()); Duas formas para instanciar objetos da classe Circulo. Estudo de Caso Classe Professor Definir construtores para: Inicializar um professor informando um nome, número de matrícula e carga horária; Inicializar um professor informando o nome e número de matrícula, com carga horária padrão de 12 horas semanais. Professor - nome: String - matricula: int - cargahoraria: int + setnome (n: String) + getnome ( ): String + setmatricula (m: int) + getmatricula( ): int + setcargahoraria (c: int) + getcargahoraria( ): int + getcargahorariamensal( ): float 5
Estudo de Caso: construtores 1 public class Professor { public Professor(String n, int m, int c) { setnome(n); setmatricula(m); setcargahoraria(c); public Professor(String n, int m) { setnome(n); setmatricula(m); setcargahoraria(12); Observando mais de perto a implementação dos dois construtores da classe Professor: Nota-se que o segundo construtor (o construtor com dois parâmetros) possui o mesmo código de inicialização do primeiro construtor (o construtor com três parâmetros). Repetir desnecessariamente código não é uma boa prática de programação. Java permite compartilhar código entre os diversos construtores!!! Palavra-chave this(). Estudo de Caso: construtores 2 public class Professor { public Professor(String n, int m, int c) { setnome(n); setmatricula(m); setcargahoraria(c); public Professor(String n, int m) { this(n,m,12); Um construtor pode chamar outro construtor da mesma classe utilizando a chamada this( ). Deve obrigatoriamente ser o primeiro comando do corpo de definição do construtor sobrecarregado. 6
Exercícios 1) Altere a classe Ponto, definida em um exercício anterior, para apresentar três construtores: um construtor sem parâmetros, que cria um ponto nas coordenadas (0,0), um construtor que recebe dois parâmetros de coordenadas X e Y, e um construtor que inicializa o ponto através das coordenadas de um outro ponto recebido como argumento. 2) Utilizando a classe Ponto, introduza novos métodos na classe Circulo, através da sobrecarga, para realizar as seguintes funções: - construir novos círculos através da informação de um ponto central e raio; - construir novos círculos através da informação de um ponto central e diâmetro; - mover um círculo para um novo ponto central qualquer. 3) Desenvolva um programa em Java para testar todos os novos métodos desenvolvidos no exercício anterior para a classe Circulo. 7
4) Você está desenvolvendo um sistema de cálculos matemáticos e se depara com um problema: a necessidade de utilização de números complexos. Solicitando ajuda de um matemático, você obtém as seguintes informações: - Números complexos possuem a forma parte real + parte imaginária * i como por exemplo 1+3i. - i representa a raiz quadrada de -1. - O número complexo resultante da soma é aquele cuja parte real é a soma das partes reais dos operandos, e a parte imaginária é a soma das partes imaginárias dos operandos. - O número complexo resultante da subtração é aquele cuja parte real é a diferença das partes reais dos operandos, e a parte imaginária é a diferença das partes imaginárias dos operandos. - Números complexos podem ser representados por extensão, como 1+3i, ou por uma forma resumida pelo par (parte real, parte imaginária), como (1,3). - Um número real a qualquer, é representado pelo número complexo (a,0). Modele e implemente as estruturas necessárias para a utilização de números complexos em um programa Java. Atributos e Métodos de Classe Java permite declarar duas categorias distintas de atributos e métodos: atributos de instância atributos de classe métodos de instância métodos de classe 8
Atributos de Classe Cada objeto de uma classe possui sua própria cópia de todos os atributos de instância da classe. Em certos casos, entretanto, é interessante que apenas uma cópia de um atributo em particular seja compartilhada por todos os objetos de uma classe. Exemplo: constantes da classe Math As constantes matemáticas E e PI são armazenadas em um única cópia e então compartilhadas. public class TestaMath { public static void main(string args[]) { System.out.println("PI = " + Math.PI); System.out.println("E = " + Math.E); Note que os atributos públicos não foram acessados a partir de um objeto! Os atributos foram acessados a partir do nome da classe! Atributos de Instância: Cada objeto possui uma cópia particular com seus valores. Representam o estado de um objeto em particular. Atributos de Classe: Cada classe possui uma única cópia do atributo, independente do número de objetos instanciados a partir da classe. Objetos compartilham os atributos de classe. São declarados pela palavra-chave static. Invocação <nome_classe>.<nome_atributo_público> 9
Exemplo: classe Circulo Nos métodos de cálculo da área e circunferência, percebe-se a presença de um valor importante em cálculos geométricos que se repete para todas as instâncias. Esse valor é a constante pi. Pode ser desejado manter somente uma cópia desse valor, com a aproximação desejada no número de suas casas decimais de uma forma consistente, impedindo que em um método seja utilizado o valor 3,14 e em outro 3,1415. PI será declarado como atributo de classe (static) e constante (final). public class Circulo { public static final double PI = 3.14; private int centrox; private int centroy; private int raio; public double area() { return (PI * raio * raio); public double circunferencia() { return (2 * PI * raio); Métodos de Classe Em muitos exemplos de classes pode-se notar alguns métodos que não acessam nenhum atributo de uma instância. Exemplo: funções trigonométricas da classe Math Os métodos sin, cos e tan recebem o valor do ângulo (em radianos) por parâmetro e devolvem o seno, cosseno ou a tangente correspondente calculados unicamente a partir do valor recebido. 10
public class Trigonometria { public static void main(string args[]) { System.out.println("Seno(45) = " + Math.sin(Math.PI/4)); System.out.println("Coseno(45) = " + Math.cos(Math.PI/4)); System.out.println("Tangente(45) = " + Math.tan(Math.PI/4)); Note que os métodos de cálculo não foram executados sobre um objeto! Métodos foram acessados pelo nome da classe! Métodos de Instância: Fornecem o comportamento dos objetos instanciados a partir de uma classe. Trabalham sobre os atributos de um objeto dessa classe. Métodos de Classe: Fornecem um comportamento que é independente da existência de objetos de uma classe. Pertencem à classe e são compartilhados por todas as instâncias da classe. Trabalham sobre os atributos de classe e valores recebidos por parâmetro. Indicados pela palavra-chave static. Invocação <nome_classe>.<nome_método>(<parâmetros>) Exemplo: classe Circulo O método equacaogeral será acrescentado à classe Circulo. Seu propósito é, a partir dos valores de centro e raio de um círculo, obter a representação textual da chamada equação geral da circunferência. public class Circulo { public String equacaogeral(int x, int y, int r) { //corpo omitido 11
Utilizando a definição em um exemplo: Circulo circulo1 = new Circulo(1,1,1); String eq = circulo1.equacaogeral(2,3,1); equacaogeral(2,3,1) circulo1:circulo x2 + y2-4x -6y + 12 = 0 O método equacaogeral realiza seu cálculo a partir dos valores recebidos como argumento, sem utilizar os atributos do objeto circulo1! Isso é um sinal de que o método deve ser implementado como um método de classe, pois é capaz de calcular a equação sem necessitar de um objeto círculo! public class Circulo { public static String equacaogeral(int x, int y, int r) { int a = -2 * x; int b = -2 * y; int c = (x*x) + (y*y) - (r*r); StringBuffer eq = new StringBuffer("x2 + y2"); if (a > 0) { eq.append(" + "); eq.append(a); eq.append("x"); else if (a < 0) { eq.append(" "); eq.append(a); eq.append("x"); if (b > 0) { eq.append(" + "); eq.append(b); eq.append("y"); else if (b < 0) { eq.append(" "); eq.append(b); eq.append("y"); if (c > 0) { eq.append(" + "); eq.append(c); else if (c < 0) { eq.append(" "); eq.append(c); eq.append(" = 0"); return eq.tostring(); 12
Utilizando a nova definição em um exemplo: String eq = Circulo.equacaoGeral(2,3,1); equacaogeral(2,3,1) Circulo x2 + y2-4x -6y + 12 = 0 O método é executado sem a criação de um objeto, pois o método é da classe e não de uma instância. Um exemplo completo: public class TesteCirculo { public static void main(string args[]) { Circulo circulo1 = new Circulo(2,3,1); System.out.println("Diametro do circulo1: " + circulo1.diametro()); System.out.println("Circunferencia do circulo1: " + circulo1.circunferencia()); System.out.println("Area do circulo1: " + circulo1.area()); System.out.println("Equacao de um circulo qualquer: " + Circulo.equacaoGeral(2,1,1)); Estudo de Caso 1 A famosa aplicação Alô Mundo : public class AloMundo { public static void main(string args[]) { System.out.println("Alo Mundo!"); 13
A classe AloMundo possui um método de classe, o método main. O método main é automaticamente invocado pela máquina virtual Java quando se executa a classe AloMundo. Ele é um método de classe pois não depende de nenhum objeto da classe AloMundo onde ele está declarado. A classe AloMundo referencia também um atributo de classe. A construção System.out.println() é na verdade o atributo de classe out da classe System, o qual guarda uma instância da classe PrintStream que possui um método de instância chamado println. Exercícios 1) Inclua na classe Circulo um método de instância para retornar a representação textual da equação geral de uma instância de Circulo. 2) Acrescente à classe Ponto, desenvolvida anteriormente, a capacidade de calcular a distância entre dois pontos. Para tal, é desejado o seguinte comportamento: - calcular a distância entre a instância do ponto e um outro objeto ponto qualquer; - calcular a distância entre a instância do ponto e um outro ponto dado pelas coordenadas X e Y; - calcular a distância entre dois pontos dadas as coordenadas X1, Y1 e X2, Y2. A distância entre dois pontos é calculada por ( x y 2 2 2 x1 ) + ( y2 1) 14