Você está na página 1de 14

Programação em C#

Curso: Lic. em Informática


Construtores e Heranças
Com o que vimos nas secções anteriores, nós precisamos lembrar de colocar o
nome do titular após criarmos uma nova conta em nosso sistema. Isso pode ser
visto no código a seguir:

Conta c = new Conta();


c.titular = "Guilherme";

E se esquecermos de chamar a segunda linha desse código, teremos uma conta


sem nome do titular. Mas, será que faz sentido existir uma conta sem titular?

Para evitar isso, ao construir nosso objeto temos que obrigar o desenvolvedor a
falar qual o titular da Conta .

Isto é, queremos ser capazes de alterar o comportamento da construção do objeto.


Queremos definir um novo comportamento que dirá como será construído o objeto.
Algo como:
Conta c = new Cconta("Guilherme Silveira");
Construtores e Heranças cont…
Note que esse comportamento que desejamos lembra um comportamento
normal, passando argumentos, mas com a característica especial de ser quem
constrói um objeto. Esse comportamento recebe o nome de construtor. E como
defini-lo? Similarmente a um comportamento qualquer:
class Conta
{
// Outros atributos da classe Cliente
public string Titular { get; set; }
public Conta (string titular)
{
this.Titular = titular;

}}
Construtores e Heranças cont…
Imagine para classe Cliente se quiséssemos inicializa-la com múltiplos valores: o
nome, idade do Cliente durante a construção do objeto? Nesse caso,
precisaríamos de um construtor adicional na classe Cliente :

class Cliente
{
public string Nome { get; set; }
public int Idade { get; set; }
// construtor que só recebe o nome
public Cliente (string nome)
{
this.Nome = nome;
}
// construtor que recebe o nome e a idade
public Cliente (string nome, int idade)
{
this.Nome = nome;
this.Idade = idade;
}

}
Exercícios
1) Ao modelar um sistema de controle de aviões em um
aeroporto, todos os aviões possuem, obrigatoriamente, um
código e uma empresa, além disso, opcionalmente, uma
cidade de entrada e saída.
Qual solução parece ser mais fácil de manter?
 Criar um construtor para código e empresa, e quatro
propriedades: código, empresa, cidade de entrada e de
saída.
 Criar um construtor para código, empresa, entrada e saída e
são criar propriedades.
 Criar quatro propriedades: código, empresa, cidade de
entrada e de saída.
 Criar um construtor para código e empresa, e duas
propriedades cidade de entrada de saída.
Herança
Uma solução seria ter classes separadas para Conta (que é a corrente) e ContaPoupanca :

public class Conta


{
public int Numero { get; set;
}
public double Saldo { get; private set;
}
public Cliente Titular { get; set;
}
public void Saca(double valor)
{
this.Saldo -= valor;
}
public void Deposita(double valor)
{
this.Saldo += valor;
}
}
Herança
public class ContaPoupanca
{
public int Numero { get; set;}
public double Saldo { get; private set; }
public Cliente Titular { get; set; }
public void Saca(double valor)
{
this.Saldo -= (valor + 0.10);
}
public void Deposita(double valor)
{
this.Saldo += valor;
}
}

Ambas as classes possuem código bem simples, mas agora o problema é outro: a repetição de
código entre ambas as classes. Se amanhã precisarmos guardar "CPF", por exemplo, precisaremos
mexer em todas as classes que representam uma conta no sistema. Isso pode ser trabalhoso.
Herança
A ideia é, portanto, reaproveitar código. Veja que, no fim, uma ContaPoupanca é
uma Conta , pois ambos tem Numero , Saldo e Titular . A única diferença é o
comportamento no momento do saque. Podemos falar que uma ContaPoupanca
é uma Conta :

Quando uma classe é definida com o :, dizemos que ela herda da outra ( Conta ) e por
isso ela ganha todos os atributos e métodos da outra classe. Por exemplo, se
ContaPoupanca herdar de Conta , isso quer dizer que ela terá Numero , Saldo , Titular , Saca() e
Deposita() automaticamente, sem precisar fazer nada. Dizemos que a classe ContaPoupanca é
uma subclasse ou classe filha da classe Conta e que Conta é uma classe base ou classe
pai da ContaPoupanca . Veja o código a seguir:

// Arquivo ContaPoupanca.cs
public class ContaPoupanca : Conta
{}
// Código no formulário que utiliza a ContaPoupanca
ContaPoupanca c = new ContaPoupanca();

c.Deposita(100.0);
Polimorfismo
Nosso banco tem relatórios internos para saber como está a saúde
financeira da instituição, além de relatórios sobre os clientes e contas. Em
um deles, é necessário calcular a soma do saldo de todas as contas
(correntes, poupanças, entre outras) que existem no banco. Começando
com "zero reais":

public class TotalizadorDeContas


{
.

public double ValorTotal { get; private set; }

}
Polimorfismo cont…
Veja que ContaPoupanca é uma Conta . Isso é inclusive expresso através da relação de herança entre as
classes. E, já que ContaPoupanca é uma Conta , o C# permite que você passe ContaPoupanca em lugares que
aceitam referências do tipo Conta ! Linguagens orientadas a objetos, como C#, possuem essa solução
elegante pra isso. Veja o código a seguir:
public class TotalizadorDeContas
{
public double ValorTotal { get; private set; }
public void Soma(Conta conta)
{
ValorTotal += conta.Saldo;
}
}
Conta c1 = new Conta();

ContaPoupanca c2 = new ContaPoupanca();


TotalizadorDeContas t = new TotalizadorDeContas();
t.Soma(c1);
t.Soma(c2); // funciona!
Polimorfismo cont…
O código funciona! Podemos passar c2 ali para o método Soma() .

Mas como isso funciona? O C# sabe que ContaPoupanca herda todos os atributos e métodos
e Conta , e portanto, tem a certeza de que existe o atributo Saldo , e que ele poderá invocá-
o sem maiores problemas!

Agora, uma ContaPoupanca tem um novo comportamento, que permite calcular seus
rendimentos. Para isso o desenvolvedor criou um comportamento chamado

alculaRendimento() :
class ContaPoupanca : Conta
{
public void CalculaRendimento()
{
// ...
}

}
Polimorfismo cont…
Veja o método Soma() . Ele invoca também o CalculaRendimento() :

public class TotalizadorDeContas


{
public double ValorTotal { get; private set;}
public void Soma(Conta conta)
{
ValorTotal += conta.Saldo;
conta.CalculaRendimento(); // não compila!
}
}

O código anterior não compila. Por quê? Porque o C# não consegue


garantir que o que virá na variável conta será uma ContaPoupanca . Naquela
"porta" entra Conta ou qualquer filho de Conta .

Essa ideia de uma variavel conseguir referenciar seu próprio tipo ou filhos
desse tipo é conhecido por polimorfismo.
Exercícios
1. Qual a diferença entre private e protected ?
• Nenhuma. Em ambos, o atributo/método é visível para todos.
• Só a própria classe enxerga atributos/métodos private enquanto
protected é visto pela própria classe mais as classes filhas.

• Só a própria classe enxerga atributos/métodos protected enquanto


private é visto pela própria classe mais as classes filhas.

2. Para que serve a palavra override ?


• Para indicar que o método está sobrescrevendo um método da
classe pai.
• Para não permitir acesso ao atributo por outras classes.
• Para indicar que esse método não deve ser utilizado.
Exercícios cont…
3. Pra que serve a palavra virtual ?
• Para permitir que o método seja sobrescrito.
• Para indicar que esse método não deve ser sobrescrito.
• Para sobrescrever um método da classe pai.
• Para não permitir acesso ao atributo por outras classes.

Você também pode gostar