Criar método em classe filha que não está na classe pai [resolvido]

13 respostas
C

Olá!
Estou fazendo um exercício simples de POO, mas não consigo criar um método em uma classe filha de uma classe abstrata.

public class Main {
    public static void main(String s[])
    {
        float n = 4f; 
        Forma quadrado = new Quadrado();
        quadrado.setLado(n);
        System.out.print(quadrado.calcularArea());
    }
}
public abstract class Forma
{
    public abstract float calcularArea(); 
}
public class Quadrado extends Forma
{
    private float lado;
    
    public void setLado(float valor)
    {
        lado = valor;
    }
    
    public float calcularArea()
    {
        return lado * lado;
    }
}

Quando compilo esse código, recebo:

Main.java:6: error: cannot find symbol
        quadrado.setLado(n);
                ^
  symbol:   method setLado(float)
  location: variable quadrado of type Forma
1 error

:’( Preciso de ajuda

Desde já, muito obrigado.

13 Respostas

W

A variável quadrado é do tipo Forma e Forma não tem um método chamado setLado, apenas Quadrado tem esse método.

Mude o tipo de quadrado para Quadrado ou mude o método setLado para a classe Forma.

A vantagem do polimorfismo é poder reusar funcionalidades comuns a um grupo de objetos… No seu exemplo, toda forma pode calcular sua área.

A partir do momento que uma certa classe tem funcionalidades específicas que você precisa e que só ela tem, não faz sentido instancia-la em uma variável de sua classe mãe.

C

Mas nesse caso eu também tenho as classes retangulo e círculo. Elas não têm setLado, mas calculam sua área. Eu pretendia ter um Forma formas[] e instanciar cada um em certo momento. Não posso?

W

Com certeza deve haver formas bem elegantes de fazer o que você quer, mas por agora o que eu consigo pensar é em definir os propriedades de cada forma em seu construtor.

class Quadrado extends Forma {
  /* ... */
  Quadrado(float lado) {
    this.lado = lado;
  }
  /* ... */
}

class Triangulo extends Forma {
  /* ... */
  Triangulo(float base, float altura) {
    this.base   = base;
    this.altura = altura;
  }
  /* ... */
}

class Circulo extends Forma {
  /* ... */
  Circulo(float raio) {
    this.raio = raio;
  }
  /* ... */
}
C

Sim. Mas, não posso ter métodos na minha classe filha que não estejam na classe pai, usando dessa forma?

W

Você pode definir métodos na classe filha da forma que quiser, você apenas não poderá involcá-los a partir de uma variável cujo tipo é o da classe pai.

Considere as seguintes classes:

class Animal {
    void print() {
        System.out.println("Animal");
    }
}

class Gato extends Animal {
    void print() {
        System.out.println("Gato");
    }

    void coisaQueSoGatoFaz() {
        System.out.println("Apenas gato sabe fazer...");
    }
}

class Cachorro extends Animal {
    void print() {
        System.out.println("Cachorro");
    }

    void coisaQueSoCachorroFaz() {
        System.out.println("Apenas cachorro sabe fazer...");
    }
}

public class Teste {
    public static void main(String[] args) {
        fazAlgumaCoisaComQualquerAnimal( new Animal() );
        fazAlgumaCoisaComQualquerAnimal( new Gato() );
        fazAlgumaCoisaComQualquerAnimal( new Cachorro() );
    }

    public static void fazAlgumaCoisaComQualquerAnimal(Animal animal) {
        animal.print();
    }
}

O método fazAlgumaCoisaComQualquerAnimal espera receber um Animal como argumento. Java conhece Animal e sabe que ele tem um método print que pode ser invocado e sabe também que o tipo Animal pode conter qualquer outra classe que possa extendê-la.

Logo, Java não permite que você invoque coisaQueSoGatoFaz a partir de uma variável do tipo Animal, pois esta variável poderia conter qualquer subclasse de Animal e não há como assegurar que cada uma dessas classes possuem um método com a mesma assinatura (nome, lista de parametros e tipo de retorno).

Imagine isso:

void meuMaravilhosMetodo(Animal animal) {
    animal.coisaQueSoGatoFaz();
}

Alguém (ou você mesmo) poderia invocar o método acima assim:

meuMaravilhosMetodo( new Gato() );

… e estaria OK, mas este alguém tem toda a liberdade pra fazer isso:

meuMaravilhosMetodo( new Cachorro() );

/* ou */

meuMaravilhosMetodo( new Bufalo() ); // considerando que Bufalo extenda Animal ^^

E se isso acontecer um erro vai ocorrer. Percebe como nem faz sentido tentar invocar coisaQueSoGatoFaz ou coisaQueSoCachorroFaz a partir de um tipo Animal?

Agora uma questão: Então como é que eu consigo invocar o método print e ele imprime a mensagem correta?

Java sabe qual tipo de objeto foi instanciado naquela variável e sabe que ele extende Animal, por isso ele tem absoluta certeza de que este objeto possui um método print, pois o herdou de sua super classe.

Por isso ele permite que invoquemos este método, pois é um método que ele pode garantir que existirá em qualquer subclasse de Animal.

Eu sei, repeti muito Animal e coisas assim, mas foi um jeito didático que encontrei para tentar explicar, espero que seja útil.

C

Bom, entendi, mas, o exercício é o seguinte:
Preciso ler n formas geométricas, podendo ser circulo, retângulo ou quadrado. Eu pensei em declarar Forma formas[n] e em um loop, instanciar os objetos das classes corretas, q seriam escolhidas pelo usuário em tempo de execução. Como eu posso aplicar isso? Não posso usar construtor nesse exercício.

Muito obrigado, desde já!
:slight_smile:

W

Ah, tá. Bom, pensei numa solução horrivel, mas é tudo o que consegui, espero que lhe dê alguma idéia:

public abstract class Forma {
  public abstract float calcularArea();

  /*
   * Os métodos abaixo não fazem nada a menos que sejam
   * sobreescritos nas subclasses em que são relevantes
   */
  public void setLado(float lado) { }
  public void setRaio(float raio) { }
  public void setBaseEAltura(float base, float altura) { }
}

public class Quadrado {
  float lado;
  public void setLado(float lado) { this.lado = lado }
}

public class Circulo {
  float raio;
  public void setRaio(float raio) { this.raio = raio }
}
P

Como fazes isto? De certeza que aqui poderás criar um objeto do tipo específico (Quadrado, Circulo, Retangulo) para depois adicionar ao teu array de Forma.

A

Para criar um método em uma classe ‘filha’ de uma classe abstrata, antes tu deve criar o método na classe ‘pai’ daí e so você ir para a classe 'filha e implementar o método desejado.

C

Olá,

Já tentou o seguinte ?

...
Quadrado quadrado = new Quadrado();
quadrado.setLado(5f);

Retangulo retangulo = new Retangulo();
retangulo.setLargura(5f);
retangulo.setAltura(10f);

Forma forma;
forma = quadrado;
System.out.println(forma.calcularArea());
forma = retangulo;
System.out.println(forma.calcularArea());
...
C

Eu dei uma pesquisada… Entendi melhor alguns conceitos, enfim…

Eu fiz da forma que não queria msm. Fiz a atribuição nos construtores.

Vlw, galera!

B

Por favor coloque como resolveu o problema. Assim, as pessoas poderam analisá-la e aprender mais!
Obrigado!

C

Como comentei acima, utilizei construtores para fazer a atribuição dos valores.

Criado 9 de março de 2016
Ultima resposta 19 de abr. de 2016
Respostas 13
Participantes 6