Ocultación de información
Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 28 de 65.
La ocultación de información va un paso más allá que las variables privadas: el código que usa una clase depende únicamente de lo que hacen sus métodos públicos, nunca de cómo almacena la clase sus datos. Después, puedes cambiar el almacenamiento sin tocar ese código.
# inventory.gd
class_name Inventory
extends RefCounted
var _counts: Dictionary = {}
func add(item: String, amount: int) -> void:
_counts[item] = _counts.get(item, 0) + amount
func count(item: String) -> int:
return _counts.get(item, 0)
func remove(item: String, amount: int) -> bool:
if count(item) < amount:
return false
_counts[item] -= amount
return truemain.gd llama a add(), count() y remove() y nunca ve el Dictionary. Si más adelante Inventory guarda un Array de espacios en su lugar, solo cambia inventory.gd.
Ten cuidado con los getters que devuelven un Array o un Dictionary. GDScript entrega estos valores por referencia: quien llama obtiene el Array propio del objeto, no una copia, y puede modificarlo sin pasar por los métodos de la clase:
# quest_log.gd
var _quests: Array[String] = ["Find the key"]
func get_quests() -> Array[String]:
return _quests# main.gd
var journal := QuestLog.new()
var quests := journal.get_quests()
quests.append("Skip the boss")
print(journal.get_quests()) # ["Find the key", "Skip the boss"]Devuelve una copia en su lugar. duplicate() crea un nuevo Array con los mismos elementos, así que los cambios que hagas en él quedan fuera del objeto:
func get_quests() -> Array[String]:
return _quests.duplicate()Para un Dictionary o un Array que contiene otros Array, usa duplicate(true): también copia los Array y Dictionary internos.
Desafío
FácilEscribe la clase Playlist en playlist.gd. Mantiene los títulos de las canciones en el Array privado _songs, y el resto del código usa solo estos métodos:
add(title)agrega el título y devuelvetrue. Si el título ya está en la lista de reproducción, no cambia nada y devuelvefalse.remove(title)elimina el título y devuelvetrue, o devuelvefalsesi no está.count()devuelve el número de canciones.get_titles()devuelve una copia de los títulos, en el orden en que se agregaron.
El código proporcionado lee el número de comandos, luego un comando por línea (add Blue Sky o remove Blue Sky) e imprime el resultado. Al final, toma el Array de get_titles(), agrega Intruder y lo invierte, luego imprime el número de canciones y los títulos. Tu lista de reproducción no debe verse afectada por esos cambios. Para los comandos add Blue Sky, add Rain y add Blue Sky, imprime:
Added: Blue Sky
Added: Rain
Already in the playlist: Blue Sky
Songs: 2
Blue Sky, RainTu código va en playlist.gd. main.gd contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
extends Node
func _ready():
# Código de entrada/salida proporcionado: mantenlo tal como está
var playlist := Playlist.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ", true, 1)
var title := parts[1]
if parts[0] == "add":
if playlist.add(title):
print("Added: " + title)
else:
print("Already in the playlist: " + title)
elif playlist.remove(title):
print("Removed: " + title)
else:
print("Not found: " + title)
# Código que intenta modificar la lista que recibe
var titles := playlist.get_titles()
titles.append("Intruder")
titles.reverse()
print("Songs: %d" % playlist.count())
print(", ".join(playlist.get_titles()))
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de la programación orientada a objetos
Archivos externosIntroducción a la programación orientada a objetosClases vs. objetosLa palabra clave selfMétodosPropiedadesConstructor (_init)Repaso: calculadora sencilla4Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas7Señales
¿Qué es una señal?Declarar y emitirConectarse a las señalesSeñales con argumentosRepaso: sistema de salud10Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite2Propiedades de clase
Variables de instancia y estáticasFunciones estáticasMétodos setter de propiedadesMétodos getter de propiedadesPrivado por convenciónRepaso: administrador de cuentas bancarias5Encapsulación
Miembros públicos y privadosValidación con settersOcultación de informaciónPropiedades de solo lecturaRepaso: sistema de registros de estudiantes8Conceptos avanzados de POO
Composición frente a herenciaClases internasNodos como componentesRefCounted frente a NodeEnums en clases3Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosCadenas de herenciaComprobaciones de tipo con isRepaso: jerarquía de empleados6Métodos especiales
Introducción a los métodos virtualesEl método _to_stringIteradores personalizadosRepaso: lista personalizada9Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de GDScript online