4.1 Classe
Uma classe é uma estrutura que abstrai um conjunto de objetos do mesmo tipo . É nela que são definidas as características (estrutura) dos objetos daquele tipo, ou seja, que dados (atributos) são armazenados pelo objeto e que operações (métodos) podem ser efetuadas com estes dados.
É importante que cada classe tenha apenas uma ou um pequeno número de responsabilidades. Se uma classe possui excesso de responsabilidades, sua implementação se tornará muito confusa e difícil de manter e entender. Pois, nesse caso, ao alterar uma responsabilidade, você correrá o risco de alterar outro comportamento inadvertidamente. Ela também centralizará muito conhecimento, que seria melhor gerenciado se fosse espalhado. Quando uma classe fica grande demais, ela quase se torna um programa completo e pode cair nos problemas da programação procedimental.
A definição básica de uma classe deverá ter mais ou menos o seguinte aspecto:
escopo class NomeClasse
{
// Construtores
escopo NomeClasse([parâmetros])
{
// Especificações
}
//Atributos
escopo tipo nomeAtributo;
escopo tipo nomeAtributo;
// Métodos
escopotipoRetornoNomeMétodo([parâmetros])
{
// Especificações
}
}
4.1.1 Atributo
Os dados contidos em uma classe são conhecidos como atributos daquela classe e representam características presentes nos objetos do tipo da classe. Cada atributo deve ter um escopo de acessibilidade, um nome e ser de um tipo, que será ou um tipo de dado nativo da linguagem (geralmente tipos inteiro, real, caractere, string, booleano), ou outra classe já existente na linguagem ou definida pelo programador.
Por exemplo, para a classe Pessoa, que representa uma abstração de uma pessoa, seus atributos poderiam ser os seguintes: nome (cadeia), idade (inteiro), peso (real) e rg (cadeia). Consequentemente cada objeto do tipo Pessoa teria estes atributos, cada um deles com um valor específico.
Exemplo 9:
public class Pessoa
{
public string nome;
public int idade;
public double peso;
public string rg;
}
Vale ressaltar que um atributo de uma classe também pode ser declarado como sendo um objeto de outra classe. Por exemplo, na classe Pessoa, o atributo rg poderia ser da classe Rg e esta, por sua vez, teria os atributos nome, nome do pai, nome da mãe, data de nascimento, naturalidade, número do RG, etc.
Exemplo 10:
public class Rg
{
public string nome;
public string nomePai;
public string nomeMae;
public string dataNascimento;
public string naturalidade;
public string registroGeral;
}
public class Pessoa
{
public string nome;
public int idade;
public double peso;
public Rg rg;
}
4.1.2 Método
Métodos definem os comportamentos dos objetos da classe, sendo equivalentes às funções e/ou procedimentos do paradigma procedimental, mas diretamente ligados a um objeto ou uma classe. Ou seja, são trechos de código modularizados que executam uma ação com os atributos acessíveis ao seu contexto.
Assim como no paradigma procedimental, além dos métodos poderem ter suas próprias variáveis locais, estes também podem acessar as variáveis globais, que no caso da orientação a objetos são os atributos da classe ou da sua instância em questão. Estes também podem receber ou não parâmetros, e podem retornar um valor a quem o chamou (similar a uma função) ou apenas executar alguma ação com os atributos acessíveis a ele (similar a um procedimento).
Vale ressaltar que quando uma função ou procedimento do paradigma procedimental acessa uma variável global aquela variável é uma variável do programa e é visível a todo o programa, enquanto que quando um método acessa uma “variável global” (atributo definido na classe), ele acessa apenas os atributos do objeto em questão ou atributos próprios da classe, chamados estes de atributos estáticos (i.e., são atributos que não pertencem aos objetos, sendo acessáveis somente pela classe). Ou seja, quando invocamos algum método de um objeto da classe Pessoa, esse método só terá acesso aos atributos do seu objeto, não “enxergando” quaisquer atributos de outros objetos do tipo Pessoa.
Como vimos, métodos são extremamente necessários na manipulação dos atributos dos objetos e são utilizados para definir o comportamento destes. Consequentemente são o principal meio de comunicação pelo qual o ambiente externo interage com o ambiente interno do objeto. Na classe Pessoa, por exemplo, poderíamos definir os métodos: falar(), comer() e obterIMC().
Exemplo 11:
public class Pessoa
{
public string nome;
public double peso;
public double altura;
public void falar()
{
Console.Write("Olá, meu nome é " + nome + "!");
}
public void comer(double kilos)
{
peso = peso + kilos;
}
Public double obterIMC()
{
return peso / (altura * altura);
}
}
4.1.3 Construtores e Destrutores
Construtores de instâncias, ou simplesmente construtores, são métodos chamados automaticamente quando ocorre uma instanciação de uma classe, ou seja, quando um objeto é criado. Estes realizam as ações necessárias para a inicialização correta do objeto, como por exemplo, atribuir valores aos atributos de controle interno do objeto, para que então este possa ser usado corretamente .
O método construtor deve ter o mesmo nome da classe e não deve ter tipo de retorno, nem mesmo void. Um construtor que não tem parâmetros é chamado de construtor default. O exemplo a seguir mostra um possível construtor default para a classe Pessoa, onde atribuímos valores default para idade e peso dos objetos da classe.
Exemplo 12:
public class Pessoa
{
public Pessoa()
{
idade = 0;
peso = 3.0;
}
...
}
Além da finalidade de preparar o ambiente interno para o uso do objeto, podemos também criar um método construtor que receba parâmetros com os quais podemos atribuir valores aos atributos do objeto durante sua criação, tornando o processo mais rápido.
Exemplo 13:
public class Pessoa
{
public Pessoa(string Nome, int Idade, double Peso)
{
nome = Nome;
idade = Idade;
peso = Peso;
}
...
}
Considerando o construtor parametrizado definido no Exemplo 13, os trechos de códigos apresentados nos Exemplos 14 e 15 são equivalentes (o que mostra um ganho em produtividade ao se utilizar construtores personalizados durante a inicialização do objeto).
Exemplo 14:
Pessoa fulano = new Pessoa("Fulano de Tal", 20, 63.3);
Exemplo 15:
Pessoa fulano = new Pessoa();
fulano.nome = "Fulano de Tal";
fulano.idade = 20;
fulano.peso = 63.3;
Em contraste com os métodos construtores, temos os métodos destrutores, que são executados automaticamente quando o escopo em que os objetos estão definidos é finalizado (i.e., quando uma instância de uma classe não pode ser mais referenciada, ela é removida da memória pelo mecanismo de coleta automática de lixo, também denominado Garbage Collector. Contudo, quando seu objeto utiliza recursos não gerenciáveis automaticamente, como arquivos, conexões de rede, etc. é necessário usar o destrutor para liberar esses recursos). Seu principal objetivo é a liberação de recursos alocados pelo objeto que será destruído (liberar arquivos, sockets, conexões com banco de dados, etc).
Na linguagem C# o destrutor é indicado por um método com o nome da classe, sem tipo de retorno (nem mesmo void) e sem parâmetros, com um ~ antes do nome do método.
Exemplo 16:
public class Pessoa
{
~ Pessoa()
{
//código a ser executado antes da
//destruição do objeto Pessoa
//pelo Garbage Collector
}
...
}