Na programação orientada a objetos baseada em classes, um construtor (abreviação: ctor) é um tipo especial de função chamada para a criação de um objeto. Ele prepara o novo objeto para uso, frequentemente aceitando argumentos que o construtor utiliza para definir variáveis de membro obrigatórias.

Um construtor assemelha-se a um método de instância, mas difere de um método por não ter um tipo de retorno explícito, não ser herdado implicitamente e, geralmente, possuir regras diferentes para modificadores de escopo. Os construtores frequentemente têm o mesmo nome da classe declarada. Eles têm a tarefa de inicializar os membros de dados do objeto e de estabelecer a invariante da classe, falhando caso a invariante seja inválida. Um construtor devidamente escrito deixa o objeto resultante em um estado válido. Objetos imutáveis devem ser inicializados em um construtor.

A maioria das linguagens permite a sobrecarga do construtor, de modo que pode haver mais de um construtor para uma classe, com parâmetros diferentes. Algumas linguagens levam em conta alguns tipos especiais de construtores. Construtores, que utilizam concretamente uma única classe para criar objetos e retornar uma nova instância da mesma, são abstraídos por fábricas (factories), que também criam objetos, mas podem fazê-lo de várias maneiras, usando múltiplas classes ou diferentes esquemas de alocação, como um pool de objetos.

Tipos

Construtores parametrizados Construtores que podem receber pelo menos um argumento são denominados construtores parametrizados. Quando um objeto é declarado em um construtor parametrizado, os valores iniciais devem ser passados como argumentos para a função construtora. A forma normal de declaração de objetos pode não funcionar. Os construtores podem ser chamados de forma explícita ou implícita. O método de chamar o construtor implicitamente também é chamado de método abreviado (shorthand).

class Point { private: int x; int y; public: Point() = default; Point(int x, int y): x{x}, y{y} {} // Construtor parametrizado

Point p = Point(0, 50); // Chamada explícita. Point p2(0, 50); // Chamada implícita.

Construtores padrão Se o programador não fornecer um construtor para uma classe instanciável, o compilador (como o do Java) insere um construtor padrão no código. Este construtor não é encontrado no código-fonte (o arquivo ), pois é inserido durante a compilação e existe no arquivo . O comportamento do construtor padrão depende da linguagem; ele pode inicializar os membros de dados com zero ou outros valores predefinidos, ou não fazer absolutamente nada. Em Java, um "construtor padrão" refere-se a um construtor sem argumentos (nulário) que é gerado automaticamente se nenhum outro construtor for definido. Todos os campos são deixados com seu valor inicial de (tipos inteiros), (tipos de ponto flutuante), (tipo booleano) ou (tipos de referência), etc.

class Point { private: int x; int y; public: Point(int x = 0, int y = 0); // Construtor padrão (com valores padrão).

Construtores de cópia

Assim como o C++, o Java também suporta "Construtores de Cópia". No entanto, diferentemente do C++, o Java não cria um construtor de cópia padrão se nenhum for especificado. Os construtores de cópia definem as ações executadas pelo compilador ao copiar objetos de uma classe. Um construtor de cópia possui um parâmetro formal que é do tipo da própria classe. Ele é usado para criar uma cópia de um objeto já existente da mesma classe.

Construtores de conversão Os construtores de conversão fornecem um meio para o compilador criar implicitamente um objeto pertencente a uma classe com base em um objeto de um tipo diferente. Esses construtores são geralmente invocados implicitamente para converter argumentos ou operandos para um tipo apropriado, mas também podem ser chamados explicitamente.

Construtores de movimento No C++, os construtores de movimento (move constructors) recebem uma "referência de Rvalue" para um objeto da classe e são usados para implementar a transferência de propriedade (ownership transfer) dos recursos do objeto de parâmetro.

Organização da memória Em Java, C# e VB .NET, o construtor cria objetos de tipo de referência no heap, enquanto tipos primitivos (como , , etc.) são armazenados na pilha (embora algumas linguagens permitam a alocação manual de objetos na pilha por meio de um modificador ). O VB .NET e o C# também permitem o uso do operador para criar objetos de tipo de valor, mas esses objetos são criados na pilha, independentemente de o operador ser usado ou não. Nessas linguagens, a destruição do objeto ocorre quando ele não possui mais referências, sendo então removido pelo coletor de lixo (garbage collector).

No C++, os objetos são criados na pilha quando o construtor é invocado sem o operador , e criados no heap quando o construtor é invocado com o operador (que retorna um ponteiro para o objeto). Objetos na pilha são excluídos implicitamente quando saem do escopo, enquanto objetos no heap devem ser excluídos implicitamente por um destrutor ou explicitamente usando o operador . Ao utilizar o idioma "Recurso de Aquisição é Inicialização" (RAII), o gerenciamento de recursos pode ser amplamente simplificado.

Exemplos JavaScript e TypeScript A partir do ES6, o JavaScript passou a ter construtores diretos como muitas outras linguagens de programação. Eles são escritos da seguinte forma:

class FooBar { constructor(baz) { this.baz = baz;

A classe pode ser instanciada assim:

const foo = new FooBar('7');

O equivalente a isso antes do ES6 era criar uma função que instancia um objeto da seguinte forma:

function FooBar (baz) { this.baz = baz; }

A instanciação é feita da mesma maneira que no exemplo anterior.

O equivalente em TypeScript seria:

class FooBar { baz: string;

constructor(baz: string) { this.baz = baz;

const foo: FooBar = new FooBar('7');

C Na linguagem C, não existem construtores. No entanto, é comum definir funções que criam um objeto (geralmente alocado dinamicamente), simulando o comportamento de um construtor.

#include <stdlib.h> #include <string.h>

typedef struct { char* name; int age; } Person;

// Este método cria uma instância de Person Person* createPerson(const char name[], int age) { Person* p = (Person*)malloc(sizeof(Person)); if (!p) { return NULL;

p->name = strdup(name); // Aloca e copia a string p->age = age; return p; }

// Este método destrói uma instância de Person void destroyPerson(Person* p) { if (p) { free(p->name); free(p);

C++ class Ponto { public: // Constructor Ponto() : x ( 0 ) : y ( 0 )

float x; // ponto no eixo das abscissas float y; // ponto no eixo das ordenadas

Python class Ponto: ponto1, ponto2, nome = None, None, None

def __init__(self, nome): # referências do construtor self.ponto1 = None self.ponto2 = None self.nome = nome

Java Em Java, os construtores diferem de outros métodos nos seguintes aspectos:

Construtores nunca possuem um tipo de retorno explícito. Construtores não podem ser invocados diretamente (a palavra-chave "" os invoca). Construtores não devem possuir modificadores que não sejam de acesso (como , , etc.).

Os construtores em Java realizam as seguintes tarefas, na ordem indicada:

Chamam o construtor da superclasse (se nenhum for definido explicitamente, o compilador insere uma chamada ao construtor padrão da superclasse). Inicializam as variáveis de membro com os valores especificados. Executam o corpo do construtor.

O Java permite que usuários chamem um construtor dentro de outro usando a palavra-chave , mas ela deve ser obrigatoriamente a primeira instrução do bloco.

class X { public X() { // Construtor não parametrizado this(1); // Chamada de outro construtor da mesma classe System.out.println("Chamando o construtor padrão");

public X(int a) { // Construtor parametrizado System.out.println("Chamando o construtor parametrizado");

public class Exemplo { public static void main(String[] args) { X x = new X();

A linguagem também fornece acesso ao construtor da superclasse através da palavra-chave .

class X { private int data;

public X() { this(1);

// Sobrecarga de construtor public X(int input) { data = input;

class Y extends X { private int data2;

public Y() { super(); // Chama o construtor de X data2 = 1;

public Y(int input1, int input2) { super(input1); // Chama o construtor parametrizado de X data2 = input2;

public class Exemplo { public static void main(String[] args) { Y y = new Y(42, 43);

Um construtor que não recebe argumentos é chamado de construtor "sem argumentos" (no-arg constructor).

Delphi interface

type Exemplo = class

private //declaração da campos. FX: Integer; FY: Integer;

public //declaração do construtor. constructor Create;

end;

implementation

//definição do construtor. constructor Exemplo.Create; begin FX := 0; FY := 0; end;

end.

Visual Basic Public Class Exemplo 'Declaração de variável de instância Private variavel As Single

'construtor padrão da classe Public Sub New() variavel = 0 End Sub

'sobrecarga do contrutor com um argumento Public Sub New(ByVal variavel As Single) Me.variavel = variavel End Sub End Class

PHP class Exemplo { // Exemplo de parametros public function __construct($Filtro = '', $Paginar = false, $Ordem = 'id_tabela')

$this->funcoes =& $GLOBALS['arquivo']; $this->bancoDeDados =& $GLOBALS['arquivo'];

if (!empty($Filtro))

return $this->consultar($Filtro, $Paginar, $Ordem); // consultar é um metodo da classe

Ruby Em Ruby, os construtores são criados definindo-se um método chamado . Este método é executado para inicializar cada nova instância da classe.

irb(main):001:0> class ExampleClass irb(main):002:1> def initialize irb(main):003:2> puts "Olá!" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> ExampleClass.new Olá! => #<ExampleClass:0x007fb3f4299118>

Rust A linguagem Rust não possui construtores no sentido estrito da programação orientada a objetos, mas frequentemente as estruturas (structs) possuem um método que atua essencialmente como um construtor. O tipo de retorno é geralmente indicado como .

struct Point { x: i32, y: i32, }

impl Point { // Método que atua como um construtor pub fn new(x: i32, y: i32) -> Self { Point { x, y }

fn main() { let p: Point = Point::new(10, 20); println!("Ponto está em ({}, {})", p.x, p.y); }

Eiffel Em Eiffel, as rotinas que inicializam novos objetos são chamadas de procedimentos de criação (creation procedures). Eles possuem as seguintes características:

Não possuem tipo de retorno explícito (pela própria definição de "procedimento"). São nomeados. São designados por nome como procedimentos de criação no texto da classe. Podem ser invocados explicitamente para reinicializar objetos existentes. Toda classe efetiva (ou seja, concreta ou não abstrata) deve designar pelo menos um procedimento de criação. Devem deixar o objeto recém-inicializado em um estado que satisfaça a invariante da classe.

Embora a criação de objetos envolva algumas sutilezas, a criação de um atributo com uma declaração típica expressa em uma instrução de criação consiste na seguinte sequência de etapas:

1. Criar uma nova instância direta do tipo . 2. Executar o procedimento de criação na instância recém-criada. 3. Anexar o objeto recém-inicializado à entidade .

No primeiro trecho abaixo, a classe é definida. O procedimento é codificado após a palavra-chave .

A palavra-chave introduz uma lista de procedimentos que podem ser usados para inicializar instâncias. Neste caso, a lista inclui , um procedimento com implementação vazia herdado da classe , e o procedimento codificado na classe.

class POINT create default_create, make

feature

make (a_x_value: REAL; a_y_value: REAL) do x := a_x_value y := a_y_value end

x: REAL -- Coordenada X

y: REAL -- Coordenada Y ...

No segundo trecho, uma classe que é cliente de possui declarações e do tipo .