[Pesquisar este blog]

domingo, 28 de janeiro de 2018

POO::Fundamentos-07-Construtores

POO-F-06-Sobrecarga POO-F-08-Encapsulamento
A existência de qualquer tipo de objeto, tanto no mundo real como na POO, exige que ele seja previamente criado, possibilitando que seja usado. As classes são novos tipos de dados definidos pelo programador para descrever entidades reais ou abstratas; que servem como modelo para criação dos objetos do seu tipo.

Cada objeto é uma ocorrência de uma classe, ou seja, é uma entidade distinta das demais, capaz de armazenar dados e realizar algumas ações, tal como descrito pelo seu tipo, isto é, por sua classe. Assim, vimos que o processo de criação de objetos implica em aspectos fundamentais da OO [6][7]:
  • Todo objeto é de um tipo específico/classe específica.
  • Os objetos da mesma classe, ou seja, do mesmo tipo, possuem as mesmas características (atributos) e comportamento (operações).
  • Todo objeto criado é distinto dos demais, independente de seus tipos.
  • Todo objeto tem um ciclo de vida.
  • Todo objeto é único e pode ser distinguido dos demais.
Por conta disso, a criação de objetos é uma operação essencial, denominada instanciação, muito importante na OO, que envolve um operador próprio (new nas linguagens de programação Java e C#) e também uma operação especial responsável pela inicialização dos objetos criados, chamada de construtor [4][7][11].

Um construtor é como um método ou função-membro, mas cuja responsabilidade é prover a preparação dos objetos de sua própria classe, pois os atributos (variáveis-membro) devem ser inicializados de modo adequado para que os objetos sejam consistentes e possam ser usados adequadamente. 

Embora os construtores sejam como métodos destinados à inicialização dos objetos da classe, são diferenciados das demais operações por três características [6]:
  • possuem, sempre, o exato mesmo nome da classe;
  • não declaram um valor de retorno, nem mesmo void, pois "retornam" um novo objeto de seu tipo; e
  • só podem ser acionados por meio do operador de instanciação new, ou seja, seu uso fica restrito à criação de novos objetos.
De maneira geral, a instanciação de objetos usa a sintaxe abaixo:

<Classe> objeto = new <construtor>([lista_argumentos]);

Aqui:
  • Classe indica o nome da classe que determina o tipo do objeto;
  • objeto é a variável que "contém" o objeto;
  • new é o operador especial de instanciação;
  • construtor é a operação especial da classe que prepara os novos objetos do tipo; e
  • lista_argumentos opcionalmente fornece dados para a criação do novo objeto.
A figura que segue ilustra o uso típico de construtores para uma classe Student.


Os construtores retornam uma referência para o objeto criado (que pode ser algo como seu endereço na memória ou um identificador próprio do sistema OO usado) que deve ser armazenada numa variável do tipo do objeto. Após a instanciação, o objeto criado fica disponível para utilização por meio da variável de referência, o que possibilita acessar seus atributos ou acionar seus métodos:

variavelObjeto.atributo = <expressaoTipoAtributo>;
variavalObjeto.método([listaParametros]);

Os atributos e métodos também podem ser utilizados em expressões compatíveis com o tipo do atributo ou do valor retornado pelo método.

Observe a classe Circulo, cujo código é equivalente em Java ou C#:

class Circulo {
   double raio;

   Circulo() { 
      raio = 1;
   }
   double area() {
      return 3.1415926*raio.raio;
   }
}

O tipo Circulo possui todos os elementos possíveis de uma classe [5][6][7][11]:
  • um atributo raio, que descreve uma característica dos objetos tipo círculo;
  • uma operação area(), funcionalidade que provê o cálculo da área do círculo baseada no atributo da classe;
  • um construtor Circulo(), que tem o mesmo nome da classe e inicializa novos objetos deste tipo com o valor padrão 1 para o raio.
Agora objetos do tipo Circulo podem ser criados e utilizados.

// Java
Circulo circulo = new Circulo();
System.out.println("Raio = " + circulo.raio);
System.out.println("Area = " + circulo.area());

//C#
Circulo circulo = new Circulo();
circulo.raio = 2.5;
Consule.WriteLine("Area = " + circulo.area());

Quando declaramos uma classe e não especificamos um construtor, o compilador automaticamente gera um construtor denominado default, que não realiza qualquer ação, apenas permitindo que novos objetos sejam criados. Se o programador fornece qualquer construtor, o compilador não incluir o construtor default.

Embora os atributos (campos) da classe sejam automaticamente inicializados (variáveis numéricas recebem zero, boleanas recebem false e de tipo objeto recebem null), é adequado que o programador, explicitamente, acrescente o construtor default (sem parâmetros) tornando clara a inicialização desejada para novos objetos da classe.

Tal como métodos, os construtores podem possuir parâmetros, permitindo que a criação dos objetos seja customizada. Assim como para os métodos, a sobrecarga (overload) também pode ser usada com construtores, é bastante conveniente em casos como este, para estabelecer formas diferentes para a criação de objetos.

Com uso da sobrecarga de construtores (constructor overload), a classe Circulo pode ser modificada para possuir tanto o construtor default (sem parâmetros), como um construtor parametrizado com o tamanho do círculo criado.

class Circulo {
   double raio;

   Circulo() { 
      raio = 1;
   }
   Circulo(double r) { 
      raio = r;
   }
   double area() {
      return 3.1415926*raio.raio;
   }
}

Com a presença de construtor parametrizado, a criação de novos objetos do tipo Circulo passa a exigir a indicação de um argumento que especifica o valor do raio do círculo criado, customizando a criação de objetos. Com isso temos:

Circulo outroCirculo = new Circulo(2.5);

A existência de construtores parametrizados torna mais flexível a criação de objetos, cujos campos podem ser iniciados com valores diversos adequados a cada programa. Somente com o construtor default, temos duas operações para criar um círculo customizado:

Circulo outroCirculo = new Circulo();
outroCirculo.raio = 2.5;

É muito importante observar que se forem fornecidos um ou mais construtores parametrizados, o compilador não gera o construtor default nesta situação. Quando qualquer construtor é fornecido pelo programador, o compilador não faz a adição automática do construtor default, de modo que, se desejado, o construtor default deve ser manualmente introduzido.

Sem o construtor default, torna-se obrigatório que os argumentos exigidos pelos construtores parametrizados sejam fornecidos. Isto é como afirmar que novos objetos não podem ser criados sem tais dados, o que é consistente com muitas situações da realidade: criar uma conta corrente exige um argumento com o CPF de seu titular; matricular um aluno numa disciplina requer um argumento com seu RA; fazer algum cadastro na web precisa de um endereço de e-mail; e assim por diante.

O uso de construtores permite, então, definir como novos objetos de uma classe serão construídos, possibilitando exigir dados na ocasião de sua instanciação, permitindo tanto sua customização, quanto economizando código no preparo de novas instâncias.

POO-F-06-Sobrecarga POO-F-08-Encapsulamento

Referências Bibliográficas

[1] JAMSA, K.; KLANDER, L.. Programando em C/C++: a bíblia. São Paulo: Makron Books, 1999.
[2] PAGE_JONES, M.. Fundamentos do Desenho Orientado a Objeto com UML. São Paulo: Makron Books, 2001.
[3] SOMMERVILLE, I.. Software Engineering. 6th. Ed. Harlow: Pearson, 2001.
[4] DEITEL, H.M.; DEITEL, P.J.. Java: como programar. 6a. Ed. São Paulo: Pearson Prentice-Hall, 2005.
[5] SAVITCH, W.. C++ Absoluto. São Paulo: Pearson Addison-Wesley, 2004.
[6] JANDL JR., P. Introdução ao C++. São Paulo: Futura, 2003.
[7] JANDL JR., P.. Java - guia do programador. 3a. ed. São Paulo: Novatec, 2015.
[8] RUMBAUGH, J.; BLAHA, M.; PREMERLANI, W.; EDDY, F.; LORENSEN, W.. Object-oriented modeling and design. Englewoods Cliffs: Prentice-Hall, 1991.
[9] STROUSTRUP, B.. The C++ Programming Language. 3rd Ed. Reading: Addison-Wesley, 1997.
[10] LANGSAM, Y.; AUGENSTEIN, M. J.; TENENBAUM, A. M.. Data structures using C and C++. 2nd Ed. Upper Saddle River: Prentice-Hall, 1996.
[11] WATSON, K.; NAGEL, C.; PEDERSEN, J.H.; REID, J.D.; SKINNER, M.; WHITE, E.. Beginning Microsoft Visual C# 2008. Indianapolis: Wiley Publishing, 2008.

Nenhum comentário: