Iniciando com C# – Parte 04: continuando com Orientação a Objetos - Grupo Viceri
Seguindo com orientação a objetos, vamos continuar a abordagem de conceitos importantes na vida do programador. Perdeu o começo da série? Confira os links abaixo:
Toda classe, por padrão, possui um construtor. Por mais que não o declaremos em nossa classe, ele está lá, sem corpo, nem argumentos.
Eles entram em ação quando criamos um objeto, quando instanciamos ele.
O construtor padrão é como o abaixo. O public Conta() {} está implícito nas classes, mas eu escrevi como ele seria para exemplificar.
Agora, vamos supor que aconteça o seguinte: eu tenho uma conta bancária, mas ela obrigatoriamente tem um número. E se eu quisesse "forçar" isso logo na instanciação? Dizer para quem está implementando que eu preciso que seja colocado um número para a classe ser instanciada?
Colocamos na nossa classe um construtor que recebe um parâmetro inteiro correspondente ao número da conta. Esse parâmetro será passado para a propriedade Numero da classe Conta. Dessa forma, garantimos que o objeto possuirá um número de conta ao ser instanciado.
Se não passarmos o número no nosso programa, o erro a seguir será exibido, correspondente à falta do parâmetro:
Passando o número, o erro não é mais exibido!
Podemos criar mais de um construtor também!
Assim fica na Conta.cs
Assim fica na Program.cs (duas opções de construtor)
Observação: Podemos mudar o modificador de acesso do construtor também. Utilizamos no exemplo, construtores public, mas poderíamos ter colocado private, e eles só poderiam ser utilizados dentro da classe Conta.
Vamos supor que agora queremos criar uma conta do tipo poupança. Vamos criar uma nova classe, a ContaPoupanca, que terá as mesmas propriedades e métodos da classe Conta.
Será que não há alguma maneira em que a minha conta poupança possua os mesmos métodos e propriedades da minha conta sem replicar as informações para essa nova classe? Imaginem que novos tipos de conta surjam: teríamos que repetir o processo todo novamente!
Podemos usar a herança para evitar isso: colocamos, depois de class Poupanca, ":" + nome da classe que possui as propriedades e métodos que queremos herdar (Conta).
Dessa forma, a classe ContaPoupanca continua possuindo as informações anteriores. A ContaPoupanca é filha da classe Conta, que é a classe base.
Se quisermos, na classe filha, referenciar algo da classe base, usamos a palavra reservada base.
Vamos supor que queremos acessar uma propriedade da nossa classe base, mas apenas as classes filhas deverão ter acesso. Classes externas, que não herdam da Conta, não podem manipulá-la. Alteramos o modificador de acesso para protected.
Com a Herança, vimos como podemos evitar a repetição de código entre classes que possuem propriedades e métodos em comum.
Vamos criar uma nova classe agora, a ContaCorrente, que também herdará da Conta.
Podemos efetuar saques em ambas as contas (ContaCorrente e ContaPoupanca), pois temos um método Saca na classe Conta, lembram?
Da forma que está aqui, ambas as classes filhas efetuaram o mesmo processo de saque. E se eu quiser que na ContaPoupancaeu debite R$0,10 por saque e na ContaCorrente, R$0,40?
1. Primeiro definimos a classe Conta como abstrata — isso quer dizer que ela não poderá ser instanciada. Apenas suas classes filhas poderão. Ela é uma conta genérica agora, servindo apenas de base para a construção das outras. Não é correto que instanciemos ela e criemos objetos da mesma.
2. Depois colocamos a palavra chave virtual no método Saca, que diz que esse método pode ser sobrescrito — ter seu corpo alterado — pelas classes que herdam da classe abstrata Conta.
3. Nas classes filhas, criamos outro método Saca, onde cada um terá um corpo diferente de acordo com a regra de negócio que definimos no início.
Dessa forma, estamos utilizando o conceito de Polimorfismo, alterando nas classes filhas o comportamento de um método que contém a mesma assinatura contida na classe base.
Se quisermos que obrigatoriamente as classes filhas alterem o método Saca, mudamos a palavra chave no método da classe Contade virtual para abstract e removemos sua implementação da classe Conta.
Métodos/Atributos Estáticos
Vimos que a classe é uma representação de algo existente no mundo real, e que para manipularmos seus métodos e propriedades, são necessárias instâncias delas, utilizando a palavra chave new.
Caso desejemos somar a quantidade de contas corrente criadas, poderíamos criar um novo atributo na classe ContaCorrente e colocar um incremento desse atributo no construtor da classe, para que toda vez que ela seja instanciada, o atributo seja incrementado.
No entanto, nos deparamos com um problema. Estamos querendo que esse atributo seja incrementado toda vez que instanciarmos um novo objeto do tipo ContaCorrente, mas quando instanciamos um objeto, ele passa a ter atributos novos, por ser um objeto novo. Dessa forma, o atributo que soma as contas terá novamente o valor 0 a cada nova instância.
Para sanar isso, atribuiremos este atributo à classe. Pertencendo à própria classe, ele não será limpo a cada instância nova.
Para fazer isso, adicionamos a palavra static.
Por ser da própria classe, e não de um objeto, passamos a obter esse valor no nosso programa da seguinte forma:
Não utilizamos mais primeiraConta, nem segundaConta. Utilizamos a própria classe, ContaCorrente, por ser um atributo pertencente a ela.27
Nosso console:
Era isso que queríamos!
Por hoje é só, pessoal. Na próxima, veremos a criação de um projeto de exemplo que faz uso dos conceitos que vimos nessas aulas.