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

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.

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.

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?

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;
  }
  /* ... */
}
1 curtida

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

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.

1 curtida

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:

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 }
}

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.

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.

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());
...

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!

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

1 curtida

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