terça-feira, 17 de março de 2015

Subclasses, herança e conceitos básicos

Algumas classes podem se estruturar hierarquicamente. Exemplo clássico:

Imagine que criamos a classe Shape (formas, em português), que define genericamente uma, com funções e atributos básicos comuns de todas as formas geométricas, como nome e área.

No entanto, para alguns objetos específicos, é interessante ter outros dados como diâmetro, no caso do círculo, tamanho do lado, no caso de um quadrado, ou hipotenusa, no caso de triângulos retângulos, mas que não fazem sentido serem definidos para os dois casos.

É possível definir então subclasses, que são classes que herdam atributos e funções de outras classes (chamadas de superclasses).
As subclasses herdam todos os atributos e métodos definidos na superclasse, mesmo que não definidos explicitamente na classe (por exemplo, se for omitido a declaração do método getNome na classe Triângulo, será utilizado o método definido na superclasse).

Pode ser ainda que não faça sentido instanciar um objeto Shape (queremos tratar formas específicas, e Shape é genérico). Nesse caso, declaramos Shape abstrata. Podemos declarar uma classe abstrata, mas não é possível instanciar (ou seja, podemos declarar um vetor de Shapes, mas o vetor será preenchido por Triângulos, Quadrados e Círculos, e não por Shapes puramente). Isso é uma vantagem grande quando queremos tratar os elementos que tem características diferentes como iguais (em um for, por exemplo, podemos percorrer um vetor de "coisas").

Aqui estão as classes (considere Triangle como triângulo retângulo equilatéro):
public class Shape {
    private String name;
    Shape(String n) { name = n; }
    public String getName() { return name; }
    public float calculateArea() { return 0.0f; }
   
    public static void main(String[] args) {
        Circle c = new Circle("Circle C", 3);
        Triangle s = new Triangle("Triangle S", 3);
        Shape shapeArray[] = {c, s};
        for(int i = 0; i < shapeArray.length; i++) {
            System.out.println("The area of " + shapeArray[i].getName()
                    + " is " + shapeArray[i].calculateArea() + " sq. cm.\n");
        }
    }
}

public class Circle extends Shape {
    private int radius;
    Circle(String n, int r) {
        super(n);
        radius = r;
    }
    public int getRaio() { return radius; }
   
    public float calculateArea() {
        float area;
        area = (float)(3.14*radius*radius);
        return area;
    }
}

public class Triangle extends Shape {
    private float hipotenusa;
    Triangle(String s, int h) {
        super(s);
        hipotenusa = h;
    }
    public float getHipotenusa() { return hipotenusa; }
   
    public float calculateArea() {
        float area;
        area = (float) (hipotenusa*hipotenusa/4.0);
        return area;
    }
}

Fizemos o método getRaio, getName e getHipotenusa porque não queremos que o usuário modifique os dados, mas apenas consiga lê-los (por isso nome, raio e hipotenusa são privados). Observe ainda que sobrescrevemos (overriding) alguns métodos. Isso faz com que um método da subclasse seja chamado ao invés do método da superclasse. Observe, no entanto, que é possível chamar o método equivalente da superclasse utilizando super() dentro da função.

Java permite ainda a sobrecarga de métodos (overload), em que criamos dois métodos com o mesmo nome, mas que difere no número de parâmetros (então a Java Virtual Machine saberá qual método você quer chamar).

Nenhum comentário:

Postar um comentário