Construtores da Classe, Primário e Secundários


Você pode implementar dezenas de Construtores para uma única Classe, porém apenas um deles deverá ser o Primário enquanto os demais deverão ser apenas Secundários.

Todos os construtores Secundários deverão fazer uma chamada ao construtor Primário.

Imagem

Os Construtores de Classes são utilizados para criar instâncias de Objetos.

Uma Classe pode ter vários construtores, mas somente o Primário deverá retornar uma instância de um Objeto.

Os demais construtores são apenas Secundários, pois irão fazer uso do construtor Primário.

O construtor Primário, na maioria das vezes, sempre será aquele com mais parâmetros.

Vamos a um exemplo.

type
  TUser = class
  private
    FLogin: string;
    FPassword: string;
  public
    constructor Create(const Login, Password: string);
    constructor Create(const Login: string); 
    function Login: string;
    function Password: string;
  end;
  
implementation

constructor TUser.Create(const Login, Password: string);
begin
  inherited Create;
  FLogin := Login;
  FPassword := Password;
end;

constructor TUser.Create(const Login: string);
begin
  Create(Login, '123456');
end;

function TUser.Login: string;
begin
  Result := FLogin;
end;

function TUser.Password: string;
begin
  Result := FPassword;
end;

A Classe TUser tem 2 construtores.

O segundo construtor chama o primeiro, passando um valor default para o argumento Password.

Qualquer inicialização de atributos, sejam eles passados em argumentos pelo construtor ou não, deverá ser executado em apenas um local, ou seja, o construtor Primário.

Este é um padrão que eu sigo em meus projetos.

Esse padrão simplifica muito quando quero saber sobre tudo que um Objeto utiliza, inicializa ou encapsula, bastando olhar no seu construtor Primário. Esse construtor sempre será o primeiro da lista de métodos.

Argumentos Default

A linguagem Pascal permite que funções e métodos tenham argumentos default. O exemplo acima poderia ser reescrito com apenas 1 construtor, desse jeito:

constructor Create(const Login, Password: string = '123456');

Apesar de escrever menos, eu não recomendo utilizar argumentos default.

O primeiro motivo é que não podemos nomear os argumentos. Quando temos mais de um argumento default, essa “vantagem de escrever menos” não faz muito sentido.

O segundo motivo é que eu prefiro gerar os valores default em runtime. Se eu quisesse gerar uma senha aleatória, por exemplo, bastaria criar um método RandomPassword e chamá-lo no construtor secundário, ou seja, a implementação do construtor Secundário poderia ser reescrita assim:

constructor TUser.Create(const Login: string);
begin
  Create(Login, RandomPassword);
end;

Construtores Secundários e Método New()

O uso do Método New() pode ser considerado um substituto de construtores Secundários. Se sua Classe implementa uma ou mais Interfaces, não haveria motivos de implementar construtores Secundários e Métodos New() com a mesma assinatura.

Ao invés de criar novos construtores Secundários, basta criar novas variações de Métodos New().

Exemplo:

type
  IUser = interface
    function Login: string;
    function Password: string;
  end;

  TUser = class(TInterfacedObject, IUser)
  private
    FLogin: string;
    FPassword: string;
  public
    constructor Create(const Login, Password: string);
    class function New(const Login, Password: string): IUser;
    class function New(const Login: string): IUser;
    function Login: string;
    function Password: string;
  end;

Assim a implementação de suas Classes ficam ainda mais simples, pois teriam apenas 1 construtor onde todos os argumentos são inicializados.

E você, como implementa seus construtores?

Posts Relacionados

  • Observando Objetos

  • Eventos e Objetos

  • Organização de Projetos

  • James e Testes de Unidade

  • James Package

  • Objetos Puros

  • Pacotes e Versões no Lazarus

  • Identificador Único Universal

  • Stored Procedures na Orientação a Objetos

  • Como Utilizar Herança Apropriadamente