Propriedades para Encapsulamento
Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 32 de 70.
Propriedades são a ferramenta principal para implementar o encapsulamento em C#. Em vez de expor campos diretamente, você os envolve com propriedades que controlam como os dados são acessados e modificados.
O padrão combina um campo privado com uma propriedade pública que inclui validação ou lógica em seus acessores:
public class Temperature
{
private double celsius;
public double Celsius
{
get { return celsius; }
set
{
if (value < -273.15)
celsius = -273.15; // Absolute zero minimum
else
celsius = value;
}
}
}Agora, o código externo não pode definir uma temperatura impossível. A propriedade atua como um guardião, garantindo que seu objeto permaneça sempre em um estado válido. Isso é o encapsulamento em ação - os dados internos são protegidos enquanto permanecem acessíveis por meio de uma interface controlada.
Você também pode usar propriedades para calcular valores ou disparar efeitos colaterais:
public double Fahrenheit
{
get { return celsius * 9 / 5 + 32; }
set { celsius = (value - 32) * 5 / 9; }
}O mundo externo vê duas propriedades, mas internamente existe apenas um campo. As propriedades permitem que você altere detalhes de implementação sem quebrar o código que usa sua classe - um benefício fundamental do encapsulamento adequado.
Desafio
FácilVamos construir um sistema de inventário de produtos que utiliza propriedades para proteger a integridade dos dados. Você criará uma classe onde os preços nunca podem ser negativos e as quantidades são sempre mantidas dentro de limites válidos - demonstrando como as propriedades atuam como guardiãs para seus dados.
Você organizará seu código em dois arquivos:
Product.cs: Crie uma classeProductno namespaceInventoryque gerencia informações do produto com validação através de propriedades. Seu produto precisa de:- Um campo privado
price(decimal) com uma propriedade públicaPriceque garante que o preço nunca fique abaixo de0- se alguém tentar definir um preço negativo, ele deve ser armazenado como0 - Um campo privado
quantity(int) com uma propriedade públicaQuantityque mantém os valores entre0e1000- valores abaixo de 0 tornam-se 0, valores acima de 1000 tornam-se 1000 - Uma propriedade auto-implementada pública
Name(string) - Uma propriedade somente leitura computada
TotalValueque retornaPrice * Quantity
- Um campo privado
Program.cs: No seu arquivo principal, crie umProductusando valores de entrada. Em seguida, tente modificar o preço e a quantidade com valores de entrada adicionais que podem ser inválidos. Imprima o estado do produto após a criação e após cada modificação para ver como as propriedades protegem os dados.
Você receberá cinco entradas:
- Nome do produto
- Preço inicial (decimal)
- Quantidade inicial (inteiro)
- Novo preço a ser definido (decimal, pode ser negativo)
- Nova quantidade a ser definida (inteiro, pode estar fora do intervalo)
Imprima a saída neste formato:
After creation:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
After modifications:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}Por exemplo, se as entradas forem Laptop, 999.99, 50, -100, e 1500, a saída deve ser:
After creation:
Laptop: Price=999.99, Qty=50, Total=49999.50
After modifications:
Laptop: Price=0, Qty=1000, Total=0Observe como o preço negativo tornou-se 0 e a quantidade de 1500 foi limitada a 1000. Suas propriedades estão protegendo o objeto de estados inválidos - isso é o encapsulamento em ação!
Folha de consulta
As propriedades envolvem campos privados com acesso controlado por meio dos acessores get e set, permitindo validação e encapsulamento:
public class Temperature
{
private double celsius;
public double Celsius
{
get { return celsius; }
set
{
if (value < -273.15)
celsius = -273.15;
else
celsius = value;
}
}
}As propriedades podem computar valores com base em campos internos:
public double Fahrenheit
{
get { return celsius * 9 / 5 + 32; }
set { celsius = (value - 32) * 5 / 9; }
}Propriedades somente leitura omitem o acessor set, permitindo apenas a recuperação de valores computados ou armazenados.
Experimente você mesmo
using System;
using Inventory;
class Program
{
public static void Main(string[] args)
{
// Ler as entradas
string name = Console.ReadLine();
decimal initialPrice = Convert.ToDecimal(Console.ReadLine());
int initialQuantity = Convert.ToInt32(Console.ReadLine());
decimal newPrice = Convert.ToDecimal(Console.ReadLine());
int newQuantity = Convert.ToInt32(Console.ReadLine());
// TODO: Criar um Produto usando os valores iniciais
// TODO: Imprimir o estado do produto após a criação
Console.WriteLine("After creation:");
// Formato de impressão: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
// TODO: Modificar o preço e a quantidade com os novos valores
// TODO: Imprimir o estado do produto após as modificações
Console.WriteLine("After modifications:");
// Formato de impressão: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
}
}
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 ExternosNamespaces e DiretivasIntrodução a Classes e ObjetosA Palavra-chave 'this'Métodos e ParâmetrosCampos vs PropriedadesConstrutoresInicializadores de ObjetosRecapitulação - Calculadora Simples4Herança
Sintaxe Básica de Herança (:)A Palavra-chave 'base'Palavras-chave Virtual e OverrideClasses SeladasA Classe Base 'object'Recapitulação - Hierarquia de Funcionários7Recursos Avançados
Sobrecarga de OperadoresIndexadores (this[])Sobrescrita de ToString()Métodos de ExtensãoRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoSingleton Thread-SafePadrão FactoryPadrão Observer (Eventos)Padrão Strategy2Propriedades e Membros Estáticos
Propriedades AutoimplementadasPropriedades de Apenas Leitura/EscritaCampos e Métodos EstáticosClasses EstáticasMembros com Corpo de Expressão5Polimorfismo e Interfaces
Polimorfismo: Compilação vs ExecuçãoInterface vs Classe AbstrataMúltiplas InterfacesInterfaces ExplícitasUpcasting e DowncastingRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição sobre HerançaGenerics (Classes e Métodos)Delegates e EventosAtributos e ReflectionIDisposable e a Instrução usingFundamentos de Injeção de Dependência11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Arquitetura de Classes
Dados de Instância vs EstáticosPalavras-chave 'readonly' e 'const'Campos de SuporteRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Modificadores de AcessoPropriedades para EncapsulamentoImplementação de Ocultação de DadosPadrões de ImutabilidadeRecapitulação - Registros de Estudantes9Argumentos Variáveis
A Palavra-chave 'params'Parâmetros OpcionaisArgumentos NomeadosSobrecarga de Métodos