Construtores
Tudo sobre o uso de construtores em Dart.
Construtores são funções especiais que criam instâncias de classes.
O Dart implementa muitos tipos de construtores. Exceto pelos construtores padrão, essas funções usam o mesmo nome de sua classe.
- Construtores generativos
Cria novas instâncias e inicializa variáveis de instância.
- Construtores padrão
-
Usado para criar uma nova instância quando um construtor não foi especificado. Ele não aceita argumentos e não é nomeado.
- Construtores nomeados
-
Esclarece o propósito de um construtor ou permite a criação de múltiplos construtores para a mesma classe.
- Construtores constantes
Cria instâncias como constantes de tempo de compilação.
- Construtores factory
-
Cria uma nova instância de um subtipo ou retorna uma instância existente do cache.
- Construtor de redirecionamento
Encaminha chamadas para outro construtor na mesma classe.
Tipos de construtores
#Construtores generativos
#Para instanciar uma classe, use um construtor generativo.
class Point {
// Instance variables to hold the coordinates of the point.
double x;
double y;
// Generative constructor with initializing formal parameters:
Point(this.x, this.y);
}
Construtores padrão
#Se você não declarar um construtor, o Dart usa o construtor padrão. O construtor padrão é um construtor generativo sem argumentos ou nome.
Construtores nomeados
#Use um construtor nomeado para implementar múltiplos construtores para uma classe ou para fornecer clareza extra:
const double xOrigin = 0;
const double yOrigin = 0;
class Point {
final double x;
final double y;
// Sets the x and y instance variables
// before the constructor body runs.
Point(this.x, this.y);
// Named constructor
Point.origin() : x = xOrigin, y = yOrigin;
}
Uma subclasse não herda o construtor nomeado de uma superclasse. Para criar uma subclasse com um construtor nomeado definido na superclasse, implemente esse construtor na subclasse.
Construtores constantes
#
Se sua classe produz objetos imutáveis, torne esses
objetos constantes de tempo de compilação.
Para tornar objetos constantes de tempo de compilação, defina um construtor const
com todas as variáveis de instância definidas como final.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0);
final double x, y;
const ImmutablePoint(this.x, this.y);
}
Construtores constantes nem sempre criam constantes.
Eles podem ser invocados em um contexto não-const.
Para saber mais, consulte a seção sobre usando construtores.
Construtores de redirecionamento
#
Um construtor pode redirecionar para outro construtor na mesma classe.
Um construtor de redirecionamento tem um corpo vazio.
O construtor usa this em vez do nome da classe após dois pontos (:).
class Point {
double x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(double x) : this(x, 0);
}
Construtores factory
#
Ao encontrar um dos seguintes dois casos de implementação de um construtor,
use a keyword factory:
-
O construtor nem sempre cria uma nova instância de sua classe. Embora um construtor factory não possa retornar
null, ele pode retornar:- uma instância existente de um cache em vez de criar uma nova
- uma nova instância de um subtipo
-
Você precisa executar trabalho não trivial antes de construir uma instância. Isso pode incluir verificar argumentos ou fazer qualquer outro processamento que não pode ser tratado na lista de inicializadores.
O exemplo a seguir inclui dois construtores factory.
- O construtor factory
Loggerretorna objetos de um cache. -
O construtor factory
Logger.fromJsoninicializa uma variável final de um objeto JSON.
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache = <String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
factory Logger.fromJson(Map<String, Object> json) {
return Logger(json['name'].toString());
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
Use um construtor factory como qualquer outro construtor:
var logger = Logger('UI');
logger.log('Button clicked');
var logMap = {'name': 'UI'};
var loggerJson = Logger.fromJson(logMap);
Construtores factory de redirecionamento
#Um construtor factory de redirecionamento especifica uma chamada para um construtor de outra classe para usar sempre que alguém fizer uma chamada para o construtor de redirecionamento.
factory Listenable.merge(List<Listenable> listenables) = _MergingListenable
Como construtores factory comuns também podem criar e retornar instâncias de outras classes, os factories de redirecionamento parecem desnecessários. No entanto, construtores factory de redirecionamento têm várias vantagens:
- Uma classe abstract pode fornecer um construtor constante que usa o construtor constante de outra classe.
- Um construtor factory de redirecionamento evita a necessidade de forwarders para repetir os parâmetros formais e seus valores padrão.
Tear-offs de construtor
#O Dart permite que você forneça um construtor como parâmetro sem chamá-lo. Chamado de tear-off (como você arranca os parênteses) serve como um closure que invoca o construtor com os mesmos parâmetros.
Se o tear-off é um construtor com a mesma assinatura e tipo de retorno que o método aceita, você pode usar o tear-off como parâmetro ou variável.
Tear-offs diferem de lambdas ou funções anônimas. Lambdas servem como um wrapper para o construtor, enquanto um tear-off é o construtor.
Use Tear-Offs
// Use a tear-off for a named constructor:
var strings = charCodes.map(String.fromCharCode);
// Use a tear-off for an unnamed constructor:
var buffers = charCodes.map(StringBuffer.new);
Não Lambdas
// Instead of a lambda for a named constructor:
var strings = charCodes.map((code) => String.fromCharCode(code));
// Instead of a lambda for an unnamed constructor:
var buffers = charCodes.map((code) => StringBuffer(code));
Para mais discussão, assista a este vídeo Decoding Flutter sobre tear-offs.
Sintaxe concisa de construtores
#
A partir do Dart 3.13, você pode omitir o nome da classe
ao declarar um construtor generativo ou factory dentro do corpo da classe,
usando diretamente o modificador new ou factory:
-
newounew nomeado -
factoryoufactory nomeado
Diferentemente dos construtores nomeados tradicionais (como Point.origin()),
construtores nomeados concisos não usam ponto
entre a palavra-chave (modificador) e o nome.
class Point {
double x, y;
// Concise unnamed generative constructor.
new(this.x, this.y);
// Concise named generative constructor.
new origin() : x = 0, y = 0;
// Equivalent to `factory Point.clone(Point other)`.
factory clone(Point other) => Point(other.x, other.y);
}
Essa sintaxe reduz a verbosidade e facilita a refatoração de nomes de classes.
A tabela a seguir mostra como mapear a sintaxe tradicional de construtores
para a sintaxe concisa de construtores (para uma classe chamada LongClassName):
| Original Dart syntax | Abbreviated syntax |
|---|---|
LongClassName() {} | new() {} |
LongClassName.name() {} | new name() {} |
const LongClassName(); | const new(); |
const LongClassName.name(); | const new name(); |
LongClassName(): this.other(); | new(): this.other(); |
LongClassName.name(): this(); | new name(): this(); |
const LongClassName(): this.other(); |
const new(): this.other(); |
const LongClassName.name(): this(); |
const new name(): this(); |
factory LongClassName() { ... } | factory() { ... } |
factory LongClassName.name() { ... } |
factory name() { ... } |
factory LongClassName() = D; | factory() = D; |
factory LongClassName.name() = D; | factory name() = D; |
const factory LongClassName() = D; | const factory() = D; |
const factory LongClassName.name() = D; |
const factory name() = D; |
Para uma sintaxe ainda mais concisa, em que você define campos e construtores em uma única linha, veja Construtores primários.
Inicialização de variáveis de instância
#O Dart oferece várias maneiras de inicializar variáveis de instância. Você pode atribuir valores na declaração, usar parâmetros formais de inicialização ou usar uma lista de inicializadores.
Inicializar variáveis de instância na declaração
#Inicialize as variáveis de instância quando você declarar as variáveis.
class PointA {
double x = 1.0;
double y = 2.0;
// The implicit default constructor sets these variables to (1.0,2.0)
// PointA();
@override
String toString() {
return 'PointA($x,$y)';
}
}
Usar parâmetros formais de inicialização
#Para simplificar o padrão comum de atribuir um argumento de construtor a uma variável de instância, o Dart tem parâmetros formais de inicialização.
Na declaração do construtor, inclua this.<propertyName>
e omita o corpo. A keyword this refere-se à instância atual.
Quando o conflito de nomes existe, use this.
Caso contrário, o estilo Dart omite o this.
Uma exceção existe para o construtor generativo onde
você deve prefixar o nome do parâmetro formal de inicialização com this.
Como observado anteriormente neste guia, certos construtores
e certas partes de construtores não podem acessar this. Estes incluem:
- Construtores factory
- O lado direito de uma lista de inicializadores
- Argumentos para um construtor de superclasse
Parâmetros formais de inicialização também permitem que você inicialize
variáveis de instância non-nullable ou final.
Ambos os tipos de variáveis requerem inicialização ou um valor padrão.
class PointB {
final double x;
final double y;
// Sets the x and y instance variables
// before the constructor body runs.
PointB(this.x, this.y);
// Initializing formal parameters can also be optional.
PointB.optional([this.x = 0.0, this.y = 0.0]);
}
Isso também funciona com variáveis nomeadas.
class PointC {
double x; // must be set in constructor
double y; // must be set in constructor
// Generative constructor with initializing formal parameters
// with default values
PointC.named({this.x = 1.0, this.y = 1.0});
@override
String toString() {
return 'PointC.named($x,$y)';
}
}
// Constructor using named variables.
final pointC = PointC.named(x: 2.0, y: 2.0);
Todas as variáveis introduzidas de parâmetros formais de inicialização são tanto final quanto apenas no escopo das variáveis inicializadas.
Para executar lógica que você não pode expressar na lista de inicializadores, crie um construtor factory ou método static com essa lógica. Você pode então passar os valores computados para um construtor normal.
Você pode definir parâmetros do construtor como nullable para evitar inicializá-los.
class PointD {
double? x; // null if not set in constructor
double? y; // null if not set in constructor
// Generative constructor with initializing formal parameters
PointD(this.x, this.y);
@override
String toString() {
return 'PointD($x,$y)';
}
}
Parâmetros nomeados privados
#Em Dart, campos que começam com sublinhado são privados à sua biblioteca. Para inicializar um campo privado usando um parâmetro nomeado, você pode escrever a atribuição manual na lista de inicializadores:
class Point {
final double _x;
Point({required double x}) : _x = x;
}
Você também pode inicializar campos privados diretamente
na lista de parâmetros do construtor.
Quando você prefixa o parâmetro nomeado com this._,
o compilador remove automaticamente o sublinhado para quem chama,
permitindo que use um nome público limpo:
class Point {
final double _x;
Point({required this._x});
}
Nos dois casos,
quem chama usa o nome público x na chamada:
var p = Point(x: 1.0);
Assim como os parâmetros nomeados comuns, você pode tornar os parâmetros nomeados privados opcionais ou obrigatórios. Você também pode fornecer valores padrão explícitos.
No exemplo a seguir, o parâmetro _x é opcional e o padrão é null.
O parâmetro _y também é opcional, mas tem o valor padrão explícito
0.0:
class PointPrivate {
final double? _x; // Nullable field
final double _y; // Non-nullable field
PointPrivate({this._x, this._y = 0.0});
@override
String toString() => 'PointPrivate($_x, $_y)';
}
void testPrivate() {
var p = PointPrivate(x: 1.0, y: 2.0);
print(p);
}
Restrições
#- Sem conflitos: nem o nome privado nem o nome público gerado podem coincidir com outro nome de parâmetro no mesmo construtor.
-
Somente parâmetros formais de inicialização: parâmetros nomeados em Dart, em geral,
não podem ser privados. Essa capacidade é uma exceção que se aplica apenas
a parâmetros nomeados que são parâmetros formais de inicialização (
this._campo). Você não pode usar identificadores privados para parâmetros nomeados comuns. -
Nome público válido: o nome privado precisa mapear para um identificador público válido.
Por exemplo,
this._outhis._2xsão inválidos porque não têm equivalentes públicos válidos.
Uso na lista de inicializadores
#Dentro da lista de inicializadores do construtor, referencie o parâmetro usando seu nome privado:
class PointPrivateAssert {
final double _x;
PointPrivateAssert({required this._x}) : assert(_x >= 0);
}
Interação com super parâmetros
#Ao estender uma classe que usa parâmetros nomeados privados, as subclasses usam o nome público para super parâmetrosSuper parameterUm parâmetro de construtor que passa automaticamente um argumento para o construtor da superclasse. Saiba mais.
No exemplo a seguir, a classe Tool define o campo privado _price.
Mesmo o campo sendo privado,
seu parâmetro nomeado correspondente é público (price, não _price).
Para repassar o valor,
a subclasse Hammer usa o identificador público price:
class Tool {
final int _price;
Tool({required this._price});
}
class Hammer extends Tool {
// Forwards to the public 'price' argument
Hammer({required super.price});
}
Usar uma lista de inicializadores
#Antes do corpo do construtor ser executado, você pode inicializar variáveis de instância. Separe os inicializadores com vírgulas.
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, double> json) : x = json['x']!, y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
Para validar entradas durante o desenvolvimento,
use assert na lista de inicializadores.
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
Listas de inicializadores ajudam a configurar campos final.
O exemplo a seguir inicializa três campos final em uma lista de inicializadores.
Para executar o código, clique em Run.
import 'dart:math';
class Point {
final double x;
final double y;
final double distanceFromOrigin;
Point(double x, double y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
void main() {
var p = Point(2, 3);
print(p.distanceFromOrigin);
}
Herança de construtor
#Subclasses, ou classes filhas, não herdam construtores de sua superclasse, ou classe pai imediata. Se uma classe não declarar um construtor, ela só pode usar o construtor padrão.
Uma classe pode herdar os parâmetros de uma superclasse. Estes são chamados super parâmetros
Construtores funcionam de maneira um tanto semelhante a como você chama uma cadeia de métodos static. Cada subclasse pode chamar o construtor de sua superclasse para inicializar uma instância, como uma subclasse pode chamar um método static de uma superclasse. Este processo não "herda" corpos ou assinaturas de construtores.
Construtores de superclasse não padrão
#O Dart executa construtores na seguinte ordem:
- lista de inicializadores
- construtor sem nome e sem argumentos da superclasse
- construtor sem argumentos da classe principal
Se a superclasse não tiver um construtor sem nome e sem argumentos,
chame um dos construtores na superclasse.
Antes do corpo do construtor (se houver),
especifique o construtor da superclasse após dois pontos (:).
No exemplo a seguir,
o construtor da classe Employee chama o construtor nomeado
para sua superclasse, Person. Para executar o código a seguir, clique em
Run.
class Person {
String? firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson().
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
void main() {
var employee = Employee.fromJson({});
print(employee);
// Prints:
// in Person
// in Employee
// Instance of 'Employee'
}
Como o Dart avalia os argumentos para o construtor da superclasse antes de invocar o construtor, um argumento pode ser uma expressão como uma chamada de função.
class Employee extends Person {
Employee() : super.fromJson(fetchDefaultData());
// ···
}
Super parâmetros
#Para evitar passar cada parâmetro para a invocação super de um construtor, use parâmetros super-initializer para encaminhar parâmetros para o construtor de superclasse especificado ou padrão. Você não pode usar este recurso com construtores de redirecionamento. Parâmetros super-initializer têm sintaxe e semântica como parâmetros formais de inicialização.
Se a invocação do super-constructor inclui argumentos posicionais, parâmetros super-initializer não podem ser posicionais.
class Vector2d {
final double x;
final double y;
Vector2d(this.x, this.y);
}
class Vector3d extends Vector2d {
final double z;
// Forward the x and y parameters to the default super constructor like:
// Vector3d(final double x, final double y, this.z) : super(x, y);
Vector3d(super.x, super.y, this.z);
}
Para ilustrar ainda mais, considere o exemplo a seguir.
// If you invoke the super constructor (`super(0)`) with any
// positional arguments, using a super parameter (`super.x`)
// results in an error.
Vector3d.xAxisError(super.x): z = 0, super(0); // BAD
Este construtor nomeado tenta definir o valor x duas vezes:
uma vez no construtor super e uma vez como um
parâmetro super posicional.
Como ambos endereçam o parâmetro posicional x, isso resulta em um erro.
Quando o construtor super tem argumentos nomeados, você pode dividi-los
entre parâmetros super nomeados (super.y no próximo exemplo)
e argumentos nomeados para a invocação do construtor super
(super.named(x: 0)).
class Vector2d {
// ...
Vector2d.named({required this.x, required this.y});
}
class Vector3d extends Vector2d {
final double z;
// Forward the y parameter to the named super constructor like:
// Vector3d.yzPlane({required double y, required this.z})
// : super.named(x: 0, y: y);
Vector3d.yzPlane({required super.y, required this.z}) : super.named(x: 0);
}
Salvo indicação em contrário, a documentação neste site reflete Dart 3.13.7. Página atualizada pela última vez em 2026-11-12. Ver código-fonte ou relatar um problema.
Encontrou essa página sem tradução ou que precisa de correção? Abra uma issue e nos ajude a manter esse site em PT-BR para ajudar pessoas como você.