Problema "simples" com herança

13 respostas
T

Porque a chamada do método q.getAreaQuadrado(); não está retornando a àrea do quadrado ?

É uma hierarquia de quatro níveis, aqui só vou mostrar as classes necessárias.

A saida do programa é:
[color=green]no método Quadrado.getAreaQuadrado
no método LadosIguais.getArea
Depois de chamar Quadrado.getAreaQuadrado[/color]

public class Teste {
	public static void main(String[] args) {
		Quadrado q = new Quadrado (2,2,2,2);
		
		q.getAreaQuadrado();
		System.out.println("Depois de chamar Quadrado.getAreaQuadrado");
	}
	
}
public class Quadrado extends LadosIguais {
	
	public Quadrado (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
		super.setArea();
	}
	
	public String getAreaQuadrado(){
		System.out.println("no método Quadrado.getAreaQuadrado");
		return String.format("\nA area do quadrado é: %.2f", super.getArea());
	}
}
public class LadosIguais extends Quadrilatero{
	private float area;
	
	public LadosIguais (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
	}
	
	public void setArea(){

//cacula no caso de ser um retangulo	
		if (super.getLados2(0) == super.getLados2(1))
			;
		else
			area = super.getLados2(0) * super.getLados2(1);  

//calcula no caso de ser um quadrado		
		if (super.getLados2(0)==super.getLados2(1) && super.getLados2(1) == super.getLados2(2))
			area = super.getLados2(0)*2;
	}
	
	public float getArea(){
		System.out.println("no método LadosIguais.getArea");
		return area;
	}

}
public class Quadrilatero {
	private float lado1, lado2, lado3, lado4;
	private float lados[] = new float[4];
	
	public Quadrilatero (float l1, float l2, float l3, float l4){
		lado1 = l1;
		lado2 = l2;
		lado3 = l3;
		lado4 = l4;
		
		lados[0] = lado1;
		lados[1] = lado2;
		lados[2] = lado3;
		lados[3] = lado4;
	}
	
	public float getLados2(int a){
		return lados [a];		
	}
}

13 Respostas

ViniGodoy

Nossa cara… que hierarquia complicada!

E que negócio é esse aqui?

if (super.getLados2(0) == super.getLados2(1)) ; else area = super.getLados2(0) * super.getLados2(1);

Não seria mais lógico fazer isso aqui?

if (super.getLados2(0) != super.getLados2(1)) area = super.getLados2(0) * super.getLados2(1);

ViniGodoy

Você só não está imprimindo a área do quadrado que você retorna!

Sua classe Teste deveria ser:
public class Teste {
    public static void main(String[] args) {
        Quadrado q = new Quadrado (2,2,2,2);
        
        System.out.println(q.getAreaQuadrado()); //O erro estava nessa linha
        System.out.println("Depois de chamar Quadrado.getAreaQuadrado");
    }
    
 }
ViniGodoy

Agora, algumas dicas para seu programa:

  1. Elimine as variáveis lado1, lado2, lado3 e lado4 da classe quadrilátero. Elas não servem para nada e você sempre poderá usar a matriz;

  2. LadosIguais me parece ser mais uma propriedade do que uma classe. Ainda sim, se for uma classe, faça com que o construtor aceite apenas dois lados. Assim você garante que o usuário não passará dados inválidos. Ele ficaria assim:

public LadosIguais (float l1, float l2){ super(l1, l1, l2, l2); }

Outra coisa que essa abordagem facilita é que o calculo de um quadrado fica rigosamente igual. O método setArea poderia ser:

public void setArea(){

return getLado(0) * getLado(2);

}
  1. Faça o mesmo para a classe quadrado. Como todos os lados são iguais, o construtor poderia ser:

public Quadrado(float lado) { super(lado, lado); }

  1. Não há necessidade do método getAreaQuadrado(), já que a classe pai já define getArea.

  2. Melhore o nome da classe LadosIguais. Ela tem quantos lados iguais? Se forem 2 pares, chame-a de Retangulo. Se forem os 4, não seria a própria classe quadrado? Se você quer apenas 2 lados, chame-a de DoisLadosIguais, mas estará faltando o método para calcular a área de um trapézio.

O código com as dicas aplicadas está em anexo.

T

Valeu, estava faltando mesmo imprimir o método na classe Quadrado. Eu achei que String.format() funcionasse igual o Printf().

Quanto as dicas, a nº 1 já segui.
as nº 2 e nº 3 segui mas adaptei, pois esta classe LadosIguais vai ser herdada não só pela Quadrado, mas também pela Retangulo, veja:

[img]http://br.geocities.com/toni_fatec/hierarquia_exer98..png[/img]

Com apenas o lado superior e direito é possivel dizer se ele é um retangulo ou um quadrado, e com apenas um lado calculamos um quadrado. Por isso modifiquei a classe LadosIguais, que agora tem dois construtores sobrecarregados:

public class LadosIguais extends Quadrilatero{
	private float area;

//construtor chamado na classe Quadrado	
	public LadosIguais (float lSuperior){
		super(lSuperior,lSuperior,lSuperior,lSuperior);
	}
	
//construtor chamado na classe Retangulo	
	public LadosIguais (float lSuperior, float lDireito){
		super(lSuperior, lDireito, lSuperior, lDireito);
	}
	
	public void setArea(){
//cacula no caso de ser um retangulo	
		if (super.getLados2(0) != super.getLados2(1))
			area = super.getLados2(0) * super.getLados2(1);  
//calcula no caso de ser um quadrado		
		else
			area = super.getLados2(0)*2;
	}
	
	public float getArea(){
		return area;
	}

}
A classe Quadrado:
public class Quadrado extends LadosIguais {
	
	public Quadrado (float lados){
		super(lados);
		super.setArea();
	}
	
	public String getAreaQuadrado(){
		return String.format("\nA area do quadrado é: %.2f", super.getArea());
	}
}
A classe Quadrilatero:
public class Quadrilatero {
	private float lados[] = new float[4];
	
	public Quadrilatero (float lSuperior, float lDireito, float lInferior, float lEsquerdo){
		lados[0] = lSuperior;
		lados[1] = lDireito;
		lados[2] = lInferior;
		lados[3] = lEsquerdo;
	}
	
	public float getLados2(int a){
		return lados [a];		
	}
}
E

Aham - * 2 multiplica por 2, não eleva ao quadrado como você está pensando. (Em Fortran “** 2” eleva ao quadrado, mas você não está programando em Fortran).

T

Edson Watanabe:

area = super.getLados2(0)*2;

Aham - * 2 multiplica por 2, não eleva ao quadrado como você está pensando. (Em Fortran “** 2” eleva ao quadrado, mas você não está programando em Fortran).

Ok voce está certo. Então em Java tenho duas alternativas, ou simplesmente multiplico getLados2(0) * getLados2(0) ou uso o método Math.pow da classe java.lang.Math que é implicitamente importada.
Então ficou assim:

area = (float)Math.pow((double)super.getLados2(0),2);
ViniGodoy

Um trapézio pode ter 2 lados iguais e dois diferentes. Basta que os dois lados formem o mesmo ângulo com a base (embora para lados opostos). Por exemplo, 30º e 120º em sentido horário. Isso não tornaria ele apto a ser filho de LadosIguais? Se não tornaria, então lados iguais refere-se a quadriláteros. Melhor chamar a classe de Quadrilatero ou Retangulo (e eliminar a classe retângulo, já que todo quadrilátero formado por ângulos internos retos é um retângulo, e isso inclui o quadrado.

sergiotaborda

Engraçado como um problema aparentemente simples pode ser tão complexo …

Um quadrilátero tem obviamente 4 lados e é isso a unica coisa que o faz especial. Um losango e um quadrado são quadrilateros com iguais comprimentos dos lados, todos iguais, e mesmo assim a áre não é calculada da mesma forma.

Parece-me que o problema está em tentar criar uma formula generica para o calculo da area quando na verdade essa é a tarefa que deve ser delegada a quem a sabe fazer : a própria classe.

Eis uma estrutura

abstract Quadrilatero {

  int[] lados;

 public (int ... tamanhoDosLados){
          if (tamanhoDosLados.length != 4){
              throw new IllegalArgumentException("Um quadrilatero tem que ter 4 lados. Apenas " + tamanhoDosLados.length + " foram fornecidos");
          }
 this.lados = tamanhoDosLados;

 }
  public int tamanhoDoLado (int ladoIndex){
          return lado[ladoIndex]
  }

  public int perimetro(){
 // o algoritmo do perimetro é generico.
           return lado[0] + lado[1] + lado[2] + lado[3];
  }

  abstract int area(); // o da area não

}



public Retangulo extends Quadrilatero implements Paralelogramo{

     public Retangulo (int ... lados){
           super(lados)
     }
     
      public int area (){
           // encontra os lados diferentes e multiplica 
          int[] nlados = Arrays,copyOf(lados, 4);
          Arrays.sort(nlados);
          return nlados[0]*nlados[3];
// poderia ser outro codigo. tou com preguiça de fazer um for
      }

}


public Quadrado extends Retangulo {

     public Quadrado (int lado){ // um so argumento
           super(lado,lado,lado,lado);
     }
     
      public int area (){
           return nlados[0] * nlados[0];
      }

}

public Losango extends Quadrilatero implements Paralelogramo{

    double anguloAgudo;
 // angulo em radianos
     public Losango (int lado, double anguloAgudo){
           super(lado,lado,lado,lado);
this.anguloAgudo = anguloAgudo; 
     }
     
      public int area (){
           return nlados[0] * Math.sin(anguloAgudo);
      }

}


 }

Lados todos têm, mas nem sempre a Área depende só dos lados (losango)… por isso area tem que ser abstrat e implementada por cada classe em separado

sergiotaborda

Quadrado é um caso particular de retangulo e retangulo é um caso de Quadrilatero. Portanto não tem como subtituir Quadrilatero por retangulo. Um losango é um Quadrilatero e não é um retangulo.

Claro, vc incluiu essas dos angulos internos para excluir coisas como o losango… :wink: mas isso é violar a herança de Quadrilatero

ViniGodoy

Exatamente, foi o que falei. Se ele não considera o losango e só figuras de angulos internos iguais, poderia substituir por retangulo sem problemas. Caso contrário, já não poderia chamar a classe de retângulo, como vc falou. Tudo vai depender do escopo da aplicação dele.

E

3. Implemente uma hierarquia de classes que represente figuras geométricas com quatro ângulos, onde temos como classes filhas retângulos e losangos. Neste caso, utilizando o conceito de polimorfismo, implemente um método tipo_figura, onde este método receba parâmetros para calcular o tipo de figura (se os ângulos internos forem igual a 90 graus a figura é um retângulo, se os ângulos internos forem diferente de 90 graus, mas iguais dois a dois, a figura é um losango). Lembre-se: deve-se utilizar obrigatoriamente o método super nos construtores das classes filhas

Toni_Fatec:
Porque a chamada do método q.getAreaQuadrado(); não está retornando a àrea do quadrado ?

É uma hierarquia de quatro níveis, aqui só vou mostrar as classes necessárias.

A saida do programa é:
[color=green]no método Quadrado.getAreaQuadrado
no método LadosIguais.getArea
Depois de chamar Quadrado.getAreaQuadrado[/color]

public class Teste {
	public static void main(String[] args) {
		Quadrado q = new Quadrado (2,2,2,2);
		
		q.getAreaQuadrado();
		System.out.println("Depois de chamar Quadrado.getAreaQuadrado");
	}
	
}
public class Quadrado extends LadosIguais {
	
	public Quadrado (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
		super.setArea();
	}
	
	public String getAreaQuadrado(){
		System.out.println("no método Quadrado.getAreaQuadrado");
		return String.format("\nA area do quadrado é: %.2f", super.getArea());
	}
}
public class LadosIguais extends Quadrilatero{
	private float area;
	
	public LadosIguais (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
	}
	
	public void setArea(){

//cacula no caso de ser um retangulo	
		if (super.getLados2(0) == super.getLados2(1))
			;
		else
			area = super.getLados2(0) * super.getLados2(1);  

//calcula no caso de ser um quadrado		
		if (super.getLados2(0)==super.getLados2(1) && super.getLados2(1) == super.getLados2(2))
			area = super.getLados2(0)*2;
	}
	
	public float getArea(){
		System.out.println("no método LadosIguais.getArea");
		return area;
	}

}
public class Quadrilatero {
	private float lado1, lado2, lado3, lado4;
	private float lados[] = new float[4];
	
	public Quadrilatero (float l1, float l2, float l3, float l4){
		lado1 = l1;
		lado2 = l2;
		lado3 = l3;
		lado4 = l4;
		
		lados[0] = lado1;
		lados[1] = lado2;
		lados[2] = lado3;
		lados[3] = lado4;
	}
	
	public float getLados2(int a){
		return lados [a];		
	}
}
E

4. como resolver essa qustão: Sabe-se que os valores de glicose no sangue de uma pessoa em jejum pode indicar se esta pessoa possui ou não um quadro de diabetes. Crie um método utilizando a estrutura de controle SWITCH-CASE, para calcular se uma pessoa esta com suspeita ou não de diabetes, utilizando as informações abaixo:

CONDIÇÃO VALORES (mg/dL)
NORMAL < 80
LIMIAR 80-120
SUSPEITA DE DIABETES >120

Toni_Fatec:
Porque a chamada do método q.getAreaQuadrado(); não está retornando a àrea do quadrado ?

É uma hierarquia de quatro níveis, aqui só vou mostrar as classes necessárias.

A saida do programa é:
[color=green]no método Quadrado.getAreaQuadrado
no método LadosIguais.getArea
Depois de chamar Quadrado.getAreaQuadrado[/color]

public class Teste {
	public static void main(String[] args) {
		Quadrado q = new Quadrado (2,2,2,2);
		
		q.getAreaQuadrado();
		System.out.println("Depois de chamar Quadrado.getAreaQuadrado");
	}
	
}
public class Quadrado extends LadosIguais {
	
	public Quadrado (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
		super.setArea();
	}
	
	public String getAreaQuadrado(){
		System.out.println("no método Quadrado.getAreaQuadrado");
		return String.format("\nA area do quadrado é: %.2f", super.getArea());
	}
}
public class LadosIguais extends Quadrilatero{
	private float area;
	
	public LadosIguais (float l1, float l2, float l3, float l4){
		super(l1, l2, l3, l4);
	}
	
	public void setArea(){

//cacula no caso de ser um retangulo	
		if (super.getLados2(0) == super.getLados2(1))
			;
		else
			area = super.getLados2(0) * super.getLados2(1);  

//calcula no caso de ser um quadrado		
		if (super.getLados2(0)==super.getLados2(1) && super.getLados2(1) == super.getLados2(2))
			area = super.getLados2(0)*2;
	}
	
	public float getArea(){
		System.out.println("no método LadosIguais.getArea");
		return area;
	}

}
public class Quadrilatero {
	private float lado1, lado2, lado3, lado4;
	private float lados[] = new float[4];
	
	public Quadrilatero (float l1, float l2, float l3, float l4){
		lado1 = l1;
		lado2 = l2;
		lado3 = l3;
		lado4 = l4;
		
		lados[0] = lado1;
		lados[1] = lado2;
		lados[2] = lado3;
		lados[3] = lado4;
	}
	
	public float getLados2(int a){
		return lados [a];		
	}
}
E

sergiotaborda:
Engraçado como um problema aparentemente simples pode ser tão complexo …

Um quadrilátero tem obviamente 4 lados e é isso a unica coisa que o faz especial. Um losango e um quadrado são quadrilateros com iguais comprimentos dos lados, todos iguais, e mesmo assim a áre não é calculada da mesma forma.

Parece-me que o problema está em tentar criar uma formula generica para o calculo da area quando na verdade essa é a tarefa que deve ser delegada a quem a sabe fazer : a própria classe.

Eis uma estrutura

abstract Quadrilatero {

  int[] lados;

 public (int ... tamanhoDosLados){
          if (tamanhoDosLados.length != 4){
              throw new IllegalArgumentException("Um quadrilatero tem que ter 4 lados. Apenas " + tamanhoDosLados.length + " foram fornecidos");
          }
 this.lados = tamanhoDosLados;

 }
  public int tamanhoDoLado (int ladoIndex){
          return lado[ladoIndex]
  }

  public int perimetro(){
 // o algoritmo do perimetro é generico.
           return lado[0] + lado[1] + lado[2] + lado[3];
  }

  abstract int area(); // o da area não

}



public Retangulo extends Quadrilatero implements Paralelogramo{

     public Retangulo (int ... lados){
           super(lados)
     }
     
      public int area (){
           // encontra os lados diferentes e multiplica 
          int[] nlados = Arrays,copyOf(lados, 4);
          Arrays.sort(nlados);
          return nlados[0]*nlados[3];
// poderia ser outro codigo. tou com preguiça de fazer um for
      }

}


public Quadrado extends Retangulo {

     public Quadrado (int lado){ // um so argumento
           super(lado,lado,lado,lado);
     }
     
      public int area (){
           return nlados[0] * nlados[0];
      }

}

public Losango extends Quadrilatero implements Paralelogramo{

    double anguloAgudo;
 // angulo em radianos
     public Losango (int lado, double anguloAgudo){
           super(lado,lado,lado,lado);
this.anguloAgudo = anguloAgudo; 
     }
     
      public int area (){
           return nlados[0] * Math.sin(anguloAgudo);
      }

}


 }

Lados todos têm, mas nem sempre a Área depende só dos lados (losango)… por isso area tem que ser abstrat e implementada por cada classe em separado

Criado 6 de julho de 2007
Ultima resposta 12 de mai. de 2011
Respostas 13
Participantes 5