Menu
Coddy logo textTech

Aprofundamento em Getters & Setters

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 33 de 110.

Getters e setters tornam-se ferramentas poderosas para encapsulamento quando combinados com campos privados. Eles permitem que você exponha uma interface pública limpa, enquanto mantém controle total sobre como os dados são acessados e modificados.

Um padrão comum é emparelhar um campo privado com um getter público e um setter que inclua validação:

class Temperature {
  double _celsius = 0;
  
  double get celsius => _celsius;
  
  set celsius(double value) {
    if (value < -273.15) {
      _celsius = -273.15;  // Mínimo do zero absoluto
    } else {
      _celsius = value;
    }
  }
}

Setters podem aplicar regras de negócio, garantindo que seu objeto nunca entre em um estado inválido.

Você também pode criar getters computados que derivam valores de dados privados:

class Rectangle {
  double _width;
  double _height;
  
  Rectangle(this._width, this._height);
  
  double get area => _width * _height;      // Computado
  double get perimeter => 2 * (_width + _height);
  
  double get width => _width;
  set width(double value) {
    if (value > 0) _width = value;
  }
}

Às vezes, você deseja acesso apenas de leitura. Basta fornecer um getter sem um setter:

class Order {
  final DateTime _createdAt = DateTime.now();
  
  DateTime get createdAt => _createdAt;  // Apenas leitura
}

Este padrão fornece ao código externo visibilidade sobre os dados, ao mesmo tempo que impede quaisquer modificações — o campo privado combinado com apenas um getter cria um acesso verdadeiramente apenas de leitura.

challenge icon

Desafio

Fácil

Vamos construir um sistema de inventário de produtos que demonstra o poder dos getters e setters para controlar o acesso aos dados. Você criará uma classe que protege seus dados internos enquanto fornece propriedades computadas e validação.

Você organizará seu código em dois arquivos:

  • product.dart: Defina uma classe Product que gerencia o inventário com o encapsulamento adequado. Seu produto deve ter:
    • Um String name público
    • Um double _price privado
    • Um int _quantity privado
    • Um construtor que recebe todos os três valores
    • Um getter price que retorna o preço privado
    • Um setter price que aceita apenas valores maiores que 0 (ignore valores inválidos)
    • Um getter quantity que retorna a quantidade privada
    • Um setter quantity que aceita apenas valores de 0 ou maiores (ignore valores negativos)
    • Um getter computado totalValue que retorna _price * _quantity
    • Um getter computado isInStock que retorna true se a quantidade for maior que 0
    • Um getter somente leitura sku que gera um SKU simples retornando os primeiros 3 caracteres do nome em maiúsculas seguidos pela quantidade (ex: LAP25 para "Laptop" com quantidade 25)
    • Um método displayProduct() que mostra os detalhes do produto
  • main.dart: Importe sua classe de produto e demonstre como os getters e setters controlam o acesso:
    • Crie um produto chamado 'Laptop' com preço 999.99 e quantidade 25
    • Chame displayProduct()
    • Imprima In stock: [isInStock]
    • Imprima SKU: [sku]
    • Tente definir o preço para -50.0 (deve ser ignorado)
    • Defina o preço para 899.99 (mudança válida)
    • Tente definir a quantidade para -10 (deve ser ignorada)
    • Defina a quantidade para 0 (mudança válida)
    • Chame displayProduct()
    • Imprima In stock: [isInStock]
    • Imprima SKU: [sku]

O método displayProduct() deve imprimir neste formato:

--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]

Saída esperada:

--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0

Folha de consulta

Getters e setters combinados com campos privados fornecem encapsulamento e controle sobre o acesso aos dados.

Campo Privado com Getter e Setter

class Temperature {
  double _celsius = 0;
  
  double get celsius => _celsius;
  
  set celsius(double value) {
    if (value < -273.15) {
      _celsius = -273.15;
    } else {
      _celsius = value;
    }
  }
}

Getters Computados

Getters podem derivar valores de dados privados:

class Rectangle {
  double _width;
  double _height;
  
  Rectangle(this._width, this._height);
  
  double get area => _width * _height;
  double get perimeter => 2 * (_width + _height);
  
  double get width => _width;
  set width(double value) {
    if (value > 0) _width = value;
  }
}

Acesso Somente Leitura

Forneça um getter sem um setter para propriedades de somente leitura:

class Order {
  final DateTime _createdAt = DateTime.now();
  
  DateTime get createdAt => _createdAt;
}

Experimente você mesmo

import 'product.dart';

void main() {
  // TODO: Criar um produto chamado 'Laptop' com o preço 999.99 e quantidade 25

  // TODO: Chamar displayProduct()

  // TODO: Imprimir "In stock: [isInStock]"

  // TODO: Imprimir "SKU: [sku]"

  // TODO: Tentar definir o preço como -50.0 (deve ser ignorado)

  // TODO: Definir o preço como 899.99 (mudança válida)

  // TODO: Tentar definir a quantidade como -10 (deve ser ignorada)

  // TODO: Definir a quantidade como 0 (mudança válida)

  // TODO: Chamar displayProduct()

  // TODO: Imprimir "In stock: [isInStock]"

  // TODO: Imprimir "SKU: [sku]"
}
quiz iconTeste seus conhecimentos

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