Membros públicos e privados
Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 26 de 65.
Encapsulamento significa que um objeto mantém seus dados junto com os métodos que alteram esses dados e decide quais de seus membros podem ser usados por outro código. Os membros destinados a serem usados por outro código formam a interface do objeto.
GDScript não tem palavra-chave public nem private: todos os membros podem ser acessados de fora. O guia de estilo do Godot marca os membros privados com um sublinhado inicial:
# bank_account.gd
class_name BankAccount
extends RefCounted
var owner_name: String
var _balance: int = 0
var _history: Array[String] = []
func _init(holder: String) -> void:
owner_name = holder
func deposit(amount: int) -> void:
_balance += amount
_record("deposit %d" % amount)
func get_balance() -> int:
return _balance
func _record(entry: String) -> void:
_history.append(entry)owner_name, deposit() e get_balance() são públicos, então main.gd os utiliza. _balance, _history e _record() são privados: somente o código dentro de bank_account.gd os utiliza.
# main.gd
var account := BankAccount.new("Ada")
account.deposit(50)
account.deposit(20)
print(account.owner_name) # Ada
print(account.get_balance()) # 70O sublinhado é uma convenção, não um bloqueio: account._balance = 1000000 em main.gd é executado sem nenhum erro. Mesmo assim, siga a convenção. Quando somente a classe altera _balance, um saldo incorreto só pode vir de um método em bank_account.gd, então esse é o único arquivo que você precisa verificar.
GDScript também não tem nível protected. Uma subclasse herda todos os membros, inclusive os privados, então uma SavingsAccount que extends BankAccount pode usar _balance em seus próprios métodos.
Os métodos virtuais do Godot, como _init() e _ready(), também começam com um sublinhado. O Godot os chama para você, então nunca dê o mesmo nome a um dos seus métodos privados.
Desafio
FácilFinalize a classe Hero em hero.gd. Seus membros públicos são hero_name, gain_xp(), get_xp() e get_level(). O restante é privado:
- Adicione as variáveis privadas
_xp(começa em0) e_level(começa em1). - Adicione o método privado
_update_level(), que define_levelcomo1 + _xp / 100(divisão inteira). gain_xp(amount)adicionaamounta_xp, chama_update_level()e retornatruequando o nível aumenta, oufalsecaso contrário.get_xp()eget_level()retornam os valores privados.
O código fornecido lê o nome do herói, depois quantas quantidades de XP vêm em seguida e, então, uma quantidade por linha. Após cada quantidade, ele imprime uma linha Level up! quando gain_xp() retorna true e, em seguida, o estado do herói. Para Ada e as quantidades 40, 70 e 250, ele imprime:
Ada: 40 XP, level 1
Level up! Ada is now level 2
Ada: 110 XP, level 2
Level up! Ada is now level 4
Ada: 360 XP, level 4Seu código deve ficar em hero.gd. main.gd contém o código de entrada/saída fornecido e não pode ser editado.
Experimente você mesmo
extends Node
func _ready():
# Código de entrada/saída fornecido: mantenha-o como está
var hero := Hero.new(OS.read_string_from_stdin())
var count := int(OS.read_string_from_stdin())
for i in count:
var amount := int(OS.read_string_from_stdin())
if hero.gain_xp(amount):
print("Level up! %s is now level %d" % [hero.hero_name, hero.get_level()])
print("%s: %d XP, level %d" % [hero.hero_name, hero.get_xp(), hero.get_level()])
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 da POO
Arquivos externosIntrodução à POOClasses vs. objetosA palavra-chave selfMétodosPropriedadesConstrutor (_init)Revisão - Calculadora simples4Polimorfismo
Revisitando a Sobrescrita de MétodosDuck TypingClasses e Métodos AbstratosDesign de InterfacesRevisão - Calculadora de Formas7Sinais
O que é um sinal?Declarando e emitindoConectando-se a sinaisSinais com argumentosRevisão - Sistema de saúde10Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite2Propriedades de Classe
Variáveis de Instância vs. EstáticasFunções EstáticasMétodos Setters de PropriedadeMétodos Getters de PropriedadePrivado por ConvençãoRecapitulando: Gerenciador de Conta Bancária5Encapsulamento
Membros públicos e privadosValidação com settersOcultação de informaçõesPropriedades somente para leituraRevisão - Sistema de registros de alunos8Conceitos Avançados de POO
Composição vs. HerançaClasses InternasNós como ComponentesRefCounted vs. NodeEnums em Classes3Herança
Herança básicaA palavra-chave superSobrescrita de métodosCadeias de herançaVerificações de tipo com isRevisão - Hierarquia de funcionários6Métodos especiais
Introdução aos métodos virtuaisO método _to_stringIteradores personalizadosRevisão - Lista personalizada9Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão StrategyPratique por conta própria: Compilador de GDScript online