O que são classe e objeto
Uma classe representa uma categoria, uma classificação. Nós abstraímos os elementos ao nosso redor para agrupá-los em um único tipo. Por exemplo, abstraímos todos os seres humanos do planeta dentro da classe «Pessoa». Uma pessoa concreta como Bob ou Tom é um objeto.
Uma classe funciona como um «projeto» ou um «molde», definindo a estrutura e o comportamento de todos os objetos vinculados a ela.
Vamos usar novamente a classe Pessoa como exemplo: esse modelo define tudo o que uma pessoa possui e tudo o que ela consegue fazer. Ela tem nome, braços, pernas e outros órgãos; consegue falar e raciocinar. Dados como nome ou idade são as propriedades da classe, enquanto ações como falar ou pensar são seus comportamentos. Em resumo, uma classe extrai características comuns de objetos reais. Com esse modelo, podemos criar vários objetos individuais como Jack ou Jim.
As propriedades da classe (nome, idade) e seus comportamentos (falar, pensar) são representados respectivamente por variáveis e funções.
Ela define quais propriedades (variáveis) e quais métodos (funções) cada objeto deve ter.
Uma classe pode ser comparada a uma forma de pão: ela não é um produto final. Com uma única forma, fabricamos vários pães reais, assim como uma classe gera diversos objetos.
No início da história da programação, o conceito de classe não existia. A linguagem C é um exemplo clássico: ela só trabalha com funções, variáveis e instruções — chamamos isso de programação procedural. À medida que os softwares se tornavam mais complexos, surgiram muitos problemas com esse modelo: muito código duplicado, estrutura desorganizada e falta de hierarquia. Depois, surgiu o paradigma orientado a objetos: abstraímos a lógica do programa em objetos, igual ao mundo real. Podemos comparar com uma empresa: no começo, o chefe cuida de todas as tarefas sozinho. Ao contratar funcionários, ele delega a contabilidade ao setor financeiro e o recrutamento ao RH. Com a divisão de funções, todo o fluxo fica muito mais organizado.
Um objeto é uma instância de uma classe.
Ao usar a palavra-chave new ou um construtor, a classe gera um novo objeto.
O objeto é uma entidade concreta em tempo de execução, capaz de armazenar dados e invocar métodos.
Relação entre classes e objetos
- A classe é o projeto arquitetônico; o objeto é a casa construída a partir desse projeto.
- A partir de uma única classe, criamos vários objetos, cada um com dados independentes.
- Todos os objetos criados da mesma classe compartilham os comportamentos (métodos) definidos na classe.

Agora vamos mudar para a linguagem Dart
Vamos estudar os tópicos abaixo
Dart é uma linguagem totalmente orientada a objetos: todo valor é uma instância de classe. Com exceção de Null, todas as classes herdam da classe base Object.
Dart implementa herança através da combinação de classes e Mixins
Herança simples: cada classe só pode ter uma única classe pai, mas os Mixins permitem reutilizar vários blocos de lógica de diferentes classes
Métodos de extensão: adicionar funcionalidades a uma classe sem alterar seu código fonte ou criar uma subclasse
Modificadores de classe: controlar se outras bibliotecas podem herdar ou implementar essa classe
Vamos começar a aprender sobre classes em Dart
Membros da classe
Os membros de uma classe englobam seus métodos e variáveis: são os elementos que compõem a classe.
Use o operador . para acessar membros de instância; o operador de segurança nula ?. evita exceções de ponteiro nulo
Aqui está um exemplo completo que demonstra a definição de classe, criação de objetos a partir da classe e chamada de membros pelo nome do objeto
// Definir uma classe, equivalente a criar um molde
class Point {
double x, y;
Point(this.x, this.y);
// Método de instância: calcular o quadrado da distância entre dois pontos
double distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return dx * dx + dy * dy;
}
}
void main() {
// Criar o objeto p a partir da classe Point para executar operações
var p = Point(2, 2);
// Ler variável de instância (getter implícito)
print(p.y); //2.0
// Invocar método de instância
double dist = p.distanceTo(Point(4, 4));
print(dist); // 8.0
// Acesso seguro com ?.
Point? nullablePoint;
var a = nullablePoint?.y; // Se o objeto for null, a recebe null sem lançar erro
print(a); // null
}Code language: JavaScript (javascript)

Construtores (Constructors)
Construtores padrão
Dart se diferencia de outras linguagens tipo C por suportar construtores nomeados. Na maioria das linguagens derivadas de C, o construtor precisa ter o mesmo nome da classe; já o Dart permite criar construtores com identificadores diferentes do nome da classe.
Sintaxe: NomeClasse() / NomeClasse.identificador() ;
A palavra-chave new é opcional (disponível desde o Dart 2)
class Point {
double x, y; // Duas variáveis membros para armazenar propriedades da classe
// Construtor padrão: inicializar as variáveis x e y
Point(this.x, this.y);
// Construtor nomeado Point.fromJson: inicializar x e y com dados JSON
Point.fromJson(Map<String, double> json)
: x = json['x']!,
y = json['y']!;
}
void main() {
var p1 = Point(2, 2);// Chamar o construtor padrão, passar 2 e 2 para definir x=2, y=2 em p1
var p2 = Point.fromJson({'x': 1, 'y': 2}); // Passar JSON para o construtor nomeado fromJson
// new é opcional, o comportamento é idêntico
var p3 = new Point(3, 3); // Criar objeto via construtor padrão
print("p1:(${p1.x},${p1.y}), p2:(${p2.x},${p2.y}), p3:(${p3.x},${p3.y})");
// Saída: p1:(2.0,2.0), p2:(1.0,2.0), p3:(3.0,3.0)
}Code language: JavaScript (javascript)
Construtores constantes com const
Coloque a palavra-chave const antes de um construtor para criar objetos constantes em tempo de compilação; constantes com parâmetros idênticos reutilizam a mesma instância.
class ImmutablePoint {
final double x, y;
// Regra do construtor constante: todos os membros devem ser marcados com final
const ImmutablePoint(this.x, this.y);
}
void main() {
// Criar instâncias constantes
var a = const ImmutablePoint(1, 1); // A palavra const é obrigatória aqui
var b = const ImmutablePoint(1, 1);
print(identical(a, b)); // true, apontam para o mesmo objeto
var m = const ImmutablePoint(1, 1);
var n = const ImmutablePoint(2, 1);
print(identical(m, n)); // false, valores diferentes geram objetos separados
// Sem const: objeto normal, sem compartilhamento de instância
var c = ImmutablePoint(1, 1);
print(identical(a, c)); //false
// Dentro de um contexto const, o const interno pode ser omitido
const pointMap = {
'p1': [ImmutablePoint(0, 0)],
'p2': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)]
};
print(pointMap); //{p1: [Instance of 'ImmutablePoint'], p2: [Instance of 'ImmutablePoint', Instance of 'ImmutablePoint']}
print(identical(p1, p2)); // false
print(identical(p2, p3)); // false
print(identical(p1, p3)); // false
}Code language: PHP (php)
Um construtor constante só reutiliza a mesma instância se todos os parâmetros passados forem exatamente iguais; basta um parâmetro diferente para criar dois objetos independentes.
Obter o tipo de tempo de execução de um objeto com runtimeType
Use objeto.runtimeType para obter o tipo em tempo de execução. Prefira o operador de verificação de tipo is em vez de comparações com runtimeType
class Point {
double x, y;
Point(this.x, this.y);
// Método de instância: calcular o quadrado da distância entre dois pontos
double distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return dx * dx + dy * dy;
}
}
void main() {
var p = Point(2, 3);
print("Tipo de p: ${p.runtimeType}"); // Point
// Método recomendado e estável
if (p is Point) {
print("p é uma instância de Point");
}
// Não recomendado para código de produção
if (p.runtimeType == Point) {
print("p é uma instância de Point ");
}
}Code language: JavaScript (javascript)
Variáveis de instância Instance Variables
- Tipos anuláveis não inicializados têm valor padrão
null; tipos não anuláveis devem ser obrigatoriamente inicializados - Todas as variáveis de instância geram um getter implícito automaticamente; variáveis não final ou late final sem inicialização ganham um setter automático
- Expressões de inicialização padrão de variáveis de instância não podem acessar this; variáveis late permitem acesso a this na sua inicialização
- Variáveis de instância final só recebem valor uma única vez: na declaração, por parâmetro do construtor ou na lista de inicialização do construtor
Getters e setters implícitos
class Point {
double? x; // Valor inicial null, getter + setter gerados automaticamente
double? y;
double z = 0; // Inicializado com 0
}
void main() {
var point = Point();
point.x = 4; // Invocar o setter implícito
assert(point.x == 4); // Invocar o getter implícito
assert(point.y == null);
print(point.z); // 0
}
Code language: JavaScript (javascript)
Restrição de acesso a this em expressões de inicialização
double globalX = 1.5;
class Point {
// Permitido: acessar variável global externa sem usar this
double? x = globalX;
// Erro de compilação: inicialização padrão não aceita this
// double? y = this.x;
// Permitido: variáveis late podem referenciar this na inicialização
late double? z = this.x;
// Permitido: o açúcar sintático this.x nos parâmetros do construtor não é uma expressão de inicialização
Point(this.x, this.y);
double? y;
}
void main() {
var p = Point(null, 5);
print(p.z); // null
}
Code language: JavaScript (javascript)
Três formas de inicializar variáveis de instância final
class ProfileMark {
// Forma 1: inicialização direta na declaração
final DateTime start = DateTime.now();
final String name;
// Forma 2: atribuição por parâmetro do construtor
ProfileMark(this.name);
// Forma 3: atribuição na lista de inicialização do construtor; o construtor nomeado unnamed define uma string vazia para name por padrão
ProfileMark.unnamed() : name = '';
}
void main() {
var m1 = ProfileMark("user1");
var m2 = ProfileMark.unnamed();
print(m1.name);
print(m2.name);
}
Code language: PHP (php)
Interfaces implícitas Implicit interfaces
Cada classe Dart possui uma interface implícita que contém todos os membros públicos de instância da classe.
implements: implementar uma interface, é obrigatório sobrescrever todos os métodos da interfaceextends: herdar de uma classe pai para reutilizar sua implementação- Variáveis privadas com prefixo
_xxxnão são expostas na interface
1 Implementar uma única interface
class Person {
final String _name;
Person(this._name);
// Método público da interface
String greet(String who) => "Hello $who, I'm $_name";
}
// Implementar a interface Person: obrigatório sobrescrever todos os membros da interface
class Impostor implements Person {
String get _name => "";
@override
String greet(String who) => "Hi $who, guess who?";
}
String greetBob(Person p) => p.greet("Bob");
void main() {
print(greetBob(Person("Kathy")));
print(greetBob(Impostor()));
}
Code language: PHP (php)
Quando uma subclasse sobrescreve um método da interface pai, use a anotação @override, similar ao Java. Para implementar uma interface usamos a palavra-chave implements.

2 Implementar várias interfaces
// Classe abstrata
abstract class Comparable {
int compareTo(Object other);
}
// Classe abstrata
abstract class Location {
double get x;
double get y;
}
// Implementar duas interfaces simultaneamente
class Point implements Comparable, Location {
@override
double x, y;
Point(this.x, this.y);
@override
int compareTo(Object other) {
if (other is Point) {
return (x + y).compareTo(other.x + other.y);
}
return -1;
}
}
void main() {
var p = Point(2, 3);
print(p.x);
print(p.compareTo(Point(1, 1)));
}
Code language: PHP (php)
@override
double x, y;
Essa anotação significa que essas duas propriedades sobrescrevem os getters abstratos definidos na interface pai Location.
Variáveis estáticas & métodos estáticos static
1. Variáveis estáticas static (variáveis de classe, única globalmente)
- Pertencem à classe, não às instâncias; inicialização tardia: só são criadas no primeiro acesso
- Constantes estáticas devem ser nomeadas em camelCase minúsculo
class Queue {
static const initialCapacity = 16; // Constante estática
static int count = 0; // Variável estática mutável
Queue() {
count++;
}
}
void main() {
assert(Queue.initialCapacity == 16); // Inicializa no acesso, valor padrão 16
Queue(); // Incrementar count em 1
Queue();
print(Queue.count); // 2
}
Code language: JavaScript (javascript)
2. Métodos estáticos static (métodos de classe)
- Não possuem referência
this, não conseguem acessar membros de instância; apenas variáveis estáticas - Chamada direta pela sintaxe
NomeClasse.metodo() - Podem ser passados como constantes de compilação para construtores constantes
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
// Método estático: calcular a distância reta entre dois pontos
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var dist = Point.distanceBetween(a, b);
print(dist); // ~2,828
}Code language: JavaScript (javascript)

Métodos estáticos pertencem à classe, por isso devem ser chamados através do nome da classe, passando duas instâncias de Point como parâmetros.