Dúvidas sobre Heranças e Polimorfismo

Olá a todos, sou iniciante em Java e estou estudando pela apostila do Caelum que está me ajudando muito.

Observem o código abaixo:

[code]class Conta {
private double saldo;

void deposita(double valor) {
    this.saldo += valor;
}
void saca(double valor) {
    this.saldo -= valor;
}
double getSaldo() {
    return this.saldo;   
}
void atualiza(double taxa) {
    this.saldo += this.saldo * taxa;
}

}
class ContaCorrente extends Conta {
@Override
void atualiza(double taxa) {
this.saldo += this.saldo * taxa * 2;
}
}
class ContaPoupanca extends Conta {
@Override
void atualiza(double taxa) {
this.saldo += this.saldo * taxa * 3;
}
}[/code]
Dúvidas:

  • porque neste caso eu tenho que usar protected para acessar o atributo herdado de Conta? não posso utilizar o getSaldo no ContaGerente e no ContaPoupança?
  • sempre será necessário utilizar protected para acessar as subclasses? uma super não iria andiantar né?
  • quando eu uso private e quando eu uso protected? qual a diferença dos 2?
  • qual a básica diferente entre Herança e Polimorfismo? Herança até deu pra entender que é onde você tem uma classe (mãe/pai) e tem as subclasses (filho) que herdam tudo o que tem da superclasse, mas Polimorfismo realmente ficou complicado de entender. :slight_smile:

Obrigado a todos desde já.

Você poderia usar o getSaldo para recuperar o valor do saldo, mas não para atualizá-lo. Seria possível o uso dos métodos se houvesse um setSaldo.

Não, private é private para a classe e para as classes internas. Qualquer outra classe, mesmo sendo filha ou estando no mesmo pacote não consegue ver os métodos privates (a não ser via reflection).

Como disse, private é somente para a classe em questão. Você quer encapsular o comportamento mesmo para os descendentes. Use protected quando vc quer permitir o acesso a atributos herdados.

Herança e polimorfismo estão ligados de várias formas, mas o polimorfismo vai além. Polimorfismo seria como vestir uma mesma roupa (interface) em vários objetos com características semelhantes.
Por exemplo, suponha que uma classe Carro e uma classe Moto implementem uma interface chamada Veiculo. Essa interface possui um método getQuantidadeRodas.
A classe Carro implementa o método com “return 4” e a classe moto com “return 2”.
Um outro método qualquer pode ter na sua assinatura um parâmetro do tipo Veiculo. Em tempo de compilação, esse método nunca saberá se o objeto recebido será uma Moto, um Carro ou qualquer outra classe que implemente a interface Veiculo.
Note que se Veiculo fosse uma classe, ao invés de interface, sendo Carro e Moto subclasses dela, o efeito seria o mesmo. Isso confunde um pouco.

a diferença de private e protected estão relacionados onde estes atributos podem ser acessados. Veja a tabela abaixo:

A diferença entre e herança e polimorfismo é:

Herança: A classe herda de alguma outra classe todos os atributos e métodos que ela possa acessar (quem define esse quais atributos e métodos que a subclasse pode acessar da superclasse são os modificadores de acesso, conforme a tabela acima). Se classeA herda ClasseB, classeA acessará todos os atributos e métodos da classeB que estiverem com o modificador de acesso public ou protected.

ContaCorrente herda os métodos e atributos de Conta

class ContaCorrente extends Conta

Polimorfismo: É quando você sobrescreve um método da sua superclasse na subclasse. Você utiliza muito isso para adaptar o método da sua superclasse na sua subclasse. Quando você implementa uma Interface, você é obrigado a usar o polimorfismo, ou então uma classe abstrata. Veja seu exemplo na classe Conta:

void atualiza(double taxa) { this.saldo += this.saldo * taxa; }

Agora veja a ContaCorrente, você sobrescreve o método atualiza da classe Conta que você herdou, ambos os métodos tem a mesma assinatura, porém comportamentos diferentes:

@Override void atualiza(double taxa) { this.saldo += this.saldo * taxa * 3; }

Só não confunda polimorfismo com sobrecarga de métodos.

A forma de explicar polimorfismo parece polimórfica…

O Pedro.Guerra explicou melhor o assunto, talvez do jeito que eu coloquei não tenha ficado tão claro…

??? :slight_smile:

  1. Não entendi! :slight_smile:
  2. Também não! :slight_smile:
  3. Sempre use private nos attributes! :slight_smile:
    A tabela do Pedro Guerra diz tudo sobre os modificadores… se inverter o padrão com o protected então dá para ver que fica uma escadinha… mais fácil de entender.
  4. Herança você disse que já entendeu… polimorfismo é herança, porém pensada de uma forma mais comportamental… normalmente com classes abstratas ou interfaces… você trabalha apenas com Conta no seu sistema… e dependendo do objeto que for (ContaCorrente ou ContaPoupança) ele terá um comportamento diferente… essa diferença é o polimorfismo.

Foi mal Scartsh escrevi errado, eu queria dizer sobrecarga de métodos, vou arrumar lá.

Mas explicando para o GbR

Sobrecarga de método são métodos que possuem o mesmo nome, o mesmo retorno, porem você pode receber parâmetros diferentes, por exemplo:

[code]public void imprimir() {
System.out.println(“Hello World”);
}

public void imprimir(String nome) {
System.out.println("Hello World, "+nome);
}

public void imprimir(String nome, int numero) {
System.out.println("Hello World, “+nome+”. Seu número é: "+numero);
}[/code]

Você pode colocar estes três métodos imprimir em ma mesma classe, que não haverá problemas, já que os parâmetros recebidos por eles são diferentes.

Polimorfismo é mudar o comportamento de uma classe que você herdou.

Só mais uma coisa para quem está com dúvida:

class ContaCorrente extends Conta

ContaCorrente herda Conta, através do comando extends. Então

ContaCorrente = subClasse
Conta = superClasse

Obrigado a todos e principalmente ao Pedro.Guerra.

Ficou uma dúvida aqui:

Agora estou confundindo Override com Polimorfismo, são a mesma coisa? :expressionless:
EDIT: Pelo visto agora estou confundindo todos overs da vida (overwrite, overrid, overload…) e também eles com Polimorfismo. :?

Salve Mano GBR!
Cara vamos por partes como já dizia um açogueiro da minha vila…rsrsrsrs!

-porque neste caso eu tenho que usar protected para acessar o atributo herdado de Conta?
è por causa das boas praticas.

metodo get(): Serve para você buscar uma varial em uma determinada classe que vc herdou ou instanciou!
Modificador protected : serve para vc definir a visualização/acesso de uma determinada variavel pois é uma boa praticar deixar os atributos protegidos.
não posso utilizar o getSaldo no ContaGerente e no ContaPoupança?
Não pois no caso vc está sobreescrevendo um metodo(Polimorfismo).
[b]

  • sempre será necessário utilizar protected para acessar as subclasses?[/b]
    protected não se usar para acessar nada e sim para determinar a visualização/acesso de um atributo.

    -uma super não iria andiantar né?

    ???Não entendi.
    [b]
  • quando eu uso private e quando eu uso protected? [/b]
    Quando vc quer determinar um nivel de restrição maior.

qual a diferença dos 2?
private : so será acessa pelos metodos da classe.
protected: será acessado pelas classe que estendem/herdem os atributos.

- qual a básica diferente entre Herança e Polimorfismo? Herança até deu pra entender que é onde você tem uma classe (mãe/pai) e tem as subclasses (filho) que herdam tudo o que tem da superclasse, mas Polimorfismo realmente ficou complicado de entender.
São coisas distitas:
Herança=voce recebe atributos e ou metodos da classe pai ou seja a classe que voce estende.
Polimorfismo = vc cria um metodo q pode ser utilizado em 2 ou + classes diferentes e vc diz no codigo o q vc quer que cada metodo faça em cada classe q está utilizando.

[quote=GbR]Obrigado a todos e principalmente ao Pedro.Guerra.

Ficou uma dúvida aqui:

Agora estou confundindo Override com Polimorfismo, são a mesma coisa? :expressionless:
EDIT: Pelo visto agora estou confundindo todos overs da vida (overwrite, overrid, overload…) e também eles com Polimorfismo. :? [/quote]

Isso, você utiliza o ‘@override’ para sobrescrever o método, ou seja, polimorfismo. Não sei agora, mas em algumas versões do JDK ele da o erro se você não colocar o @Override antes da função que já existe e vc vai reescrevê-la.

Creio eu, me corrijam se estiver enganado, mas 100% das vezes que você ver o @Override é um polimorfismo.

Então deixa eu ver se eu entendi:
overload = sobrecarga de métodos
override = reescrever; polimorfismo?

Caso esteja correta a afirmação acima, surge uma dúvida final, observe o código:

[code]
class Conta {
protected double saldo;

void deposita(double valor) {
    this.saldo += valor;
}
void saca(double valor) {
    this.saldo -= valor;
}
double getSaldo() {
    return this.saldo;   
}
void atualiza(double taxa) {
    this.saldo += this.saldo * taxa;
}

}
class ContaCorrente extends Conta {
@Override
void atualiza(double taxa) {
this.saldo += this.saldo * taxa * 2;
}
@Override
void deposita(double valor) {
this.saldo += valor - 0.10;
}
}
class ContaPoupanca extends Conta {
@Override
void atualiza(double taxa) {
this.saldo += this.saldo * taxa * 3;
}
}

public class TesteConta {
public static void main(String[] args) {
Conta c = new Conta();
ContaCorrente cc = new ContaCorrente();
ContaPoupanca cp = new ContaPoupanca();

    c.deposita(1000);
    cc.deposita(1000);
    cp.deposita(1000);
    
    c.atualiza(0.01);
    cc.atualiza(0.01);
    cp.atualiza(0.01);
    
    System.out.println(c.getSaldo());
    System.out.println(cc.getSaldo());
    System.out.println(cp.getSaldo());
}

}[/code]

Se eu trocar a linha 37 e 38 em vez de ContaCorrente e ContaPoupanca pra Conta ele irá exibir o mesmo valor. Porque acontece isso? Neste caso eu devo instanciar qual, o ContaCorrente e ContaPoupanca ou tudo Conta? Qual a diferença de deixar tudo Conta e deixar ContaCorrente e ContaPoupanca?

[quote=GbR]Então deixa eu ver se eu entendi:
overload = sobrecarga de métodos
override = reescrever; polimorfismo?
[/quote]

Isso, mas não é necessário utilizar a @Overload para sobrecarga de métodos. Agora o @Override sim.

Funciona assim:

Os construtores:

Todos são padrões, como você não declarou construtor em nenhuma classe, todos construtores ficam em branco

Conta c = new Conta(); ContaCorrente cc = new ContaCorrente(); ContaPoupanca cp = new ContaPoupanca();

Quando você deposita você utiliza o método depositar.

‘C’ é uma instancia da classe Conta, então C.deposita(1000) vai chamar o método deposita da classe Conta

void deposita(double valor) { this.saldo += valor; }

‘CC’ é isntancia da classe ContaCorrente que estende a classe Conta. Repare que na classe ContaCorrente você sobrescreveu o método deposita. Como ele foi sobrescrito, quando vc usar o código CC.deposita(1000) ele vai chamar a função deposita da classe ContaCorrente

@Override void deposita(double valor) { this.saldo += valor - 0.10; }

‘CP’ é uma instancia da classe ContaPoupanca que estende a classe Conta. Como vc não sobrescreveu o métoda da superClasse (da classe Conta), quando vc chama o método cp.deposita(1000) ele vai chamar o método deposita() da classe Conta:

void deposita(double valor) { this.saldo += valor; }

A mesma coisa acontece com o método atualiza. ‘C’ chama o método atualiza da classe Conta. ‘CC’ chama o método atualiza da classe ContaCorrente, pois vc reescreveu o método na classe. Em ‘CP’ idem a ‘CC’.

Quando você utiliza o getSaldo, como nem ContaCorrente, nem ContaPoupanca sobrescreveram este método, ele será chamado da superClasse (Conta).

Ai fica a a seu critério qual classe escolher qual classe usar. Você tem que usar a classe que vc precisa.

Obrigado por sanar as dúvidas. :wink: