Campos Final & Const
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 18 de 110.
Ao declarar campos em uma classe, você pode usar final ou const para controlar se os valores podem mudar após a inicialização. Ambos criam valores imutáveis, mas funcionam de forma diferente.
Um campo final só pode ser definido uma vez, mas seu valor é determinado em tempo de execução. Você pode atribuí-lo na declaração ou por meio de um construtor:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}
Person p = Person('Alice');
// p.name = 'Bob'; // Erro: não é possível reatribuir um campo finalO name é definido quando o objeto é criado, e o createdAt captura a hora atual. Ambos os valores são bloqueados após a inicialização.
Um campo static const deve ter um valor conhecido em tempo de compilação. Ele pertence à própria classe e é compartilhado entre todas as instâncias:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}A principal diferença: campos final podem conter valores computados em tempo de execução (como DateTime.now()), enquanto const exige constantes de tempo de compilação. Campos de instância não podem ser const diretamente - apenas static const é permitido no nível da classe.
Desafio
FácilVamos construir um sistema de catálogo de produtos que demonstra a diferença entre campos final e static const. Você criará produtos com propriedades imutáveis e valores de configuração compartilhados.
Você organizará seu código em dois arquivos:
product.dart: Defina uma classeProductque representa um item em uma loja. Sua classe deve ter:- Um
static const double taxRatedefinido como0.08(taxa de imposto de 8% compartilhada entre todos os produtos) - Um
static const String currencydefinido como'USD' - Um
final String namepara o nome do produto (definido via construtor) - Um
final double basePricepara o preço base do produto (definido via construtor) - Um
final String sku(unidade de manutenção de estoque) que combina um prefixo com o nome do produto, calculado em uma lista de inicialização como'SKU-'seguido pelo nome em maiúsculas - Um construtor que recebe
nameebasePrice - Um getter
priceWithTaxque calcula o preço incluindo o imposto - Um método
display()que imprime as informações do produto
- Um
main.dart: Importe sua classe de produto e crie dois produtos:- Um
'Laptop'com preço base999.99 - Um
'Mouse'com preço base29.99
display()em cada produto na ordem listada acima.- Um
O método display() deve imprimir exatamente neste formato:
[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])Arredonde priceWithTax para 2 casas decimais usando toStringAsFixed(2) ao exibir.
Saída esperada:
SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)Folha de consulta
Use final para campos que são definidos uma única vez em tempo de execução e não podem ser alterados posteriormente. Use static const para constantes de tempo de compilação compartilhadas entre todas as instâncias de uma classe.
Campos final são definidos em tempo de execução e podem ser inicializados na declaração ou no construtor:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}Campos static const devem ter valores constantes em tempo de compilação e pertencem à própria classe:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}Você pode calcular valores de campos final em uma lista de inicialização:
class Product {
final String name;
final String sku;
Product(this.name) : sku = 'SKU-${name.toUpperCase()}';
}Principais diferenças:
final: Valores em tempo de execução, podem ser diferentes para cada instânciastatic const: Constantes em tempo de compilação, compartilhadas entre todas as instâncias- Campos de instância não podem ser
constdiretamente - apenasstatic consté permitido
Experimente você mesmo
import 'product.dart';
void main() {
// TODO: Criar um Product chamado 'Laptop' com preço base 999.99
// TODO: Criar um Product chamado 'Mouse' com preço base 29.99
// TODO: Chamar display() em cada produto em ordem (Laptop primeiro, depois Mouse)
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosBibliotecas e ImportaçõesIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosVariáveis de InstânciaFundamentos de ConstrutoresRecapitulação - Calculadora Simples4Null Safety
Introdução ao Null SafetyNullable vs Non-NullableOs Operadores ? e !Palavra-chave Late e Null SafetyOperadores Null-AwareNull Safety em ClassesRecapitulação - Sistema de Perfil de Usuário7Classes Abstratas e Interfaces
Classes AbstratasMétodos AbstratosInterfaces em DartInterfaces ImplícitasImplementando vs EstendendoMúltiplas InterfacesRecapitulação - Calculadora de Formas10Coleções e Generics
Visão Geral de List, Set e MapColeções Type-SafeClasses GenéricasMétodos GenéricosRestrições de GenericsIterable e IteratorRecapitulação - Armazenamento Genérico13Conceitos Avançados de POO
Composição vs HerançaMétodos de ExtensãoClasses ChamáveisClasses Seladas (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums com Métodos16Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário2Construtores em Dart
Construtor PadrãoConstrutores NomeadosListas de InicializaçãoConstrutores ConstantesConstrutores FactoryConstrutores de RedirecionamentoRecapitulação - Shape Builder5Encapsulamento
Membros Públicos vs PrivadosA Convenção do Prefixo _Privacidade em Nível de BibliotecaAprofundamento em Getters & SettersOcultação de InformaçãoRecapitulação - Registros de Estudantes8Mixins
Introdução aos MixinsCriando MixinsUsando Múltiplos MixinsPalavra-chave on em MixinsMixin vs HerançaMixin vs InterfaceRecapitulação - Sistema Animal11Métodos Especiais
Sobrescrita de toString()Sobrescrita de hashCode & ==Interface ComparableMétodo call()Sobrescrita de noSuchMethodRecapitulação - Coleção Personalizada14Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy3Propriedades de Classe
Membros de Instância vs EstáticosCampos Final & ConstVariáveis LateMétodos e Campos EstáticosGetters e SettersRecapitulação - Gerenciador de Conta Bancária6Herança
Herança BásicaA Palavra-chave superSobrescrita de MétodoA Anotação @overrideA Palavra-chave final para ClassesConstrutores e HerançaRecapitulação - Hierarquia de Funcionários9Polimorfismo
Fundamentos do PolimorfismoPolimorfismo via InterfacesVerificação de Tipos em Tempo de ExecuçãoOs Operadores is & asPalavra-chave CovariantRecapitulação - Processador de Pagamentos12POO Assíncrona
Futures e async/awaitFundamentos de StreamsStream ControllersConstrutores AssíncronosAsync em Métodos de ClasseRecapitulação - Data Fetcher15Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository