Métodos Getters e Setters
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 49 de 107.
Como os campos não exportados não podem ser acessados diretamente de fora de um pacote, você precisa fornecer métodos que permitam um acesso controlado. Eles são comumente chamados de getters e setters.
Em Go, a convenção para getters é simples: use o nome do campo com a primeira letra em maiúscula. Não adicione o prefixo "Get"; use apenas Balance(), e não GetBalance():
type BankAccount struct {
balance int // não exportado
}
// Getter - retorna o valor
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - modifica o valor com validação
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
O verdadeiro poder dos setters é adicionar validação ou lógica de negócio. Em vez de permitir que o código externo defina qualquer valor diretamente, você controla o que é permitido:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Este método Deposit atua como um setter especializado que impõe regras: não são permitidos depósitos negativos. O código externo deve passar pelos seus métodos, garantindo que a struct permaneça sempre em um estado válido. Isso é encapsulamento em ação: ocultar os dados enquanto expõe um comportamento controlado.
Desafio
FácilVamos criar um conversor de temperatura que demonstra o encapsulamento adequado usando métodos getter e setter. Você criará uma struct que armazena internamente a temperatura em Celsius, mas fornece acesso controlado por meio de métodos com validação.
Você organizará seu código em dois arquivos:
temperature.go: Crie uma structTemperaturecom um campocelsiusnão exportado (float64). Implemente os seguintes métodos:Celsius()- um getter que retorna a temperatura atual em CelsiusSetCelsius(value float64)- um setter que aceita apenas valores iguais ou superiores ao zero absoluto (-273.15). Se o valor estiver abaixo desse limite, a temperatura deverá permanecer inalterada.Fahrenheit()- retorna a temperatura convertida para Fahrenheit usando a fórmula:(celsius * 9/5) + 32SetFahrenheit(value float64)- converte a entrada de Fahrenheit para Celsius e a armazena, mas somente se o valor resultante em Celsius for igual ou superior a -273.15
NewTemperature(celsius float64) *Temperatureque cria uma temperatura inicializada com o valor fornecido (considere que a entrada do construtor é válida).main.go: Leia os valores de temperatura da entrada e demonstre os métodos getter/setter. Crie uma temperatura, exiba seus valores em ambas as unidades, depois tente definir novos valores e mostre os resultados.
As seguintes entradas serão fornecidas:
- Linha 1: Valor inicial em Celsius
- Linha 2: Novo valor em Celsius a ser definido
- Linha 3: Novo valor em Fahrenheit a ser definido
Formate todas as saídas de temperatura com duas casas decimais. Imprima a seguinte sequência:
- Após a criação:
C: [celsius] F: [fahrenheit] - Após definir Celsius:
C: [celsius] F: [fahrenheit] - Após definir Fahrenheit:
C: [celsius] F: [fahrenheit]
Por exemplo, considerando 25, -300 e 212, sua saída deverá ser:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Observe que a segunda linha mostra valores inalterados porque -300 está abaixo do zero absoluto, então o setter o rejeitou. A terceira linha mostra a temperatura após definir 212°F com sucesso (que é convertido para 100°C). Esse é o poder dos setters. Eles impõem regras que mantêm seus dados válidos.
Experimente você mesmo
package main
import (
"fmt"
)
func main() {
// Ler valores de entrada
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Crie uma nova Temperature usando o construtor
// TODO: Imprima os valores iniciais no formato "C: [celsius] F: [fahrenheit]" com 2 casas decimais
// TODO: Tente definir o novo valor de Celsius e imprima o resultado
// TODO: Tente definir o novo valor de Fahrenheit e imprima o resultado
}
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 OOP em Go
Arquivos ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker PoolPratique por conta própria: Compilador de Go online