Membros Públicos vs Privados
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 30 de 110.
Encapsulamento é um dos princípios fundamentais da programação orientada a objetos. Trata-se de controlar o acesso aos dados internos de uma classe, decidindo o que deve ser visível para o mundo exterior e o que deve permanecer oculto.
No Dart, os membros de classe (campos e métodos) são públicos por padrão. Isso significa que qualquer código pode acessá-los diretamente:
class BankAccount {
String owner;
double balance;
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Qualquer pessoa pode modificar isso diretamente!Isso é problemático. Nada impede a definição de um saldo inválido.
Para proteger dados internos, o Dart usa membros privados. Um membro torna-se privado quando seu nome começa com um sublinhado _:
class BankAccount {
String owner;
double _balance; // Privado - começa com sublinhado
BankAccount(this.owner, this._balance);
double get balance => _balance; // Acesso controlado
}Agora _balance não pode ser acessado diretamente de fora da biblioteca onde a classe está definida. O código externo deve usar o getter público em seu lugar. Isso permite que você controle como os dados são lidos e modificados, garantindo que seus objetos permaneçam sempre em um estado válido.
Desafio
FácilVamos construir um gerenciador de senhas simples que demonstra a diferença entre membros públicos e privados. Você verá como o prefixo de sublinhado protege dados sensíveis de serem acessados diretamente de fora da biblioteca da classe.
Você criará dois arquivos para organizar seu código:
credential.dart: Defina uma classeCredentialque armazena informações de login para um site. A classe deve ter:- Um
String websitepúblico - não há problema em qualquer pessoa ver para qual site isso se refere - Um
String usernamepúblico - o nome de usuário pode ser visível - Um
String _passwordprivado - a senha real deve ser protegida - Um construtor que recebe todos os três valores
- Um getter público
passwordque retorna o_passwordprivado (acesso controlado) - Um método
getMaskedPassword()que retorna a senha com todos os caracteres substituídos por asteriscos*(mesmo comprimento da senha real) - Um método
displayCredential()que imprime as informações da credencial de forma segura (mostrando a senha mascarada, não a real)
- Um
main.dart: Importe sua classe de credencial e demonstre como o encapsulamento protege a senha:- Crie uma credencial para o site
'github.com', nome de usuário'dev_user'e senha'secret123' - Crie outra credencial para o site
'email.com', nome de usuário'john_doe'e senha'myP@ss' - Para cada credencial, chame
displayCredential(), depois imprimaActual password length: [length]usando o getter público para acessar o comprimento da senha
- Crie uma credencial para o site
O método displayCredential() deve imprimir neste formato:
--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]Saída esperada:
--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6Folha de consulta
O encapsulamento controla o acesso aos dados internos de uma classe, decidindo o que deve ser visível e o que deve permanecer oculto.
No Dart, os membros da classe são públicos por padrão:
class BankAccount {
String owner;
double balance; // Public - can be accessed directly
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Direct modification allowedPara proteger os dados internos, use membros privados prefixando o nome com um sublinhado _:
class BankAccount {
String owner;
double _balance; // Private - starts with underscore
BankAccount(this.owner, this._balance);
double get balance => _balance; // Controlled access via getter
}Membros privados não podem ser acessados diretamente de fora da biblioteca onde a classe está definida. Use getters e métodos públicos para fornecer acesso controlado aos dados privados, garantindo que os objetos permaneçam em um estado válido.
Experimente você mesmo
import 'credential.dart';
void main() {
// TODO: Criar uma credencial para github.com
// website: 'github.com', username: 'dev_user', password: 'secret123'
// TODO: Chamar displayCredential() na primeira credencial
// TODO: Imprimir o comprimento real da senha usando o getter público
// Formato: "Actual password length: [length]"
// TODO: Criar uma credencial para email.com
// website: 'email.com', username: 'john_doe', password: 'myP@ss'
// TODO: Chamar displayCredential() na segunda credencial
// TODO: Imprimir o comprimento real da senha usando o getter público
}
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