Getters y Setters
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 28 de 104.
Cuando los miembros de una clase son privados, el código externo no puede acceder a ellos directamente. Los getters y setters son métodos públicos que proporcionan un acceso controlado a estos miembros privados: los getters recuperan valores y los setters los modifican.
class Temperature {
double celsius; // Privado - no se puede acceder directamente
public:
// Getter - devuelve el valor
double getCelsius() const {
return celsius;
}
// Setter - modifica el valor con validación
void setCelsius(double value) {
if (value >= -273.15) { // Comprobación del cero absoluto
celsius = value;
}
}
};El verdadero poder de los setters es la validación.
En lugar de permitir que se asigne cualquier valor, puedes imponer reglas. En el ejemplo anterior, se rechazan las temperaturas por debajo del cero absoluto. Sin un setter, cualquiera podría asignar datos no válidos directamente.
Los getters también pueden transformar los datos antes de devolverlos:
class Temperature {
double celsius;
public:
double getCelsius() const { return celsius; }
// Getter calculado - no almacena fahrenheit, lo calcula
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}
void setCelsius(double value) { celsius = value; }
};Observa la palabra clave const en los getters: esto indica que no modifican el objeto. Los setters no pueden ser const, ya que su propósito es cambiar los valores de los miembros. Este patrón de usar getters y setters es fundamental para la encapsulación, ya que te brinda un control total sobre cómo se accede a los datos de tu clase y cómo se modifican.
Desafío
FácilConstruyamos un sistema de perfil de jugador que demuestre cómo los getters y setters proporcionan acceso controlado a datos privados, incluida la validación y las propiedades calculadas.
Crearás dos archivos para organizar tu código:
Player.h: Define una clasePlayerque gestione el perfil de un personaje del juego con acceso protegido a los datos. Tu clase debe tener:- Miembros privados:
name(string),level(int) yexperience(int) - Un constructor que reciba un nombre e inicialice
levelen1yexperienceen0 - Un getter
getName()que devuelva el nombre del jugador - Un getter
getLevel()que devuelva el nivel actual - Un getter
getExperience()que devuelva los puntos de experiencia actuales - Un setter
setName()que solo acepte nombres de al menos 3 caracteres; si no es válido, debe mantener el nombre actual sin cambios - Un setter
addExperience(int points)que solo acepte valores positivos. Cuando la experiencia alcance o supere100, el jugador subirá de nivel: incrementa el nivel en 1 y resta 100 a la experiencia. Esto puede ocurrir varias veces si se añade suficiente experiencia. - Un getter calculado
getExperienceToNextLevel()que devuelva cuántos puntos de experiencia más se necesitan para alcanzar el siguiente nivel (siempre100 - current experience)
Marca todos los getters como
const, ya que no modifican el objeto.- Miembros privados:
main.cpp: Demuestra tus getters y setters en acción. Lee un nombre de jugador y puntos de experiencia para añadir desde la entrada (cada uno en una línea separada) y, después:- Crea un
Playercon el nombre introducido - Imprime
"Player: <name>, Level: <level>, XP: <experience>" - Añade los puntos de experiencia introducidos usando
addExperience() - Imprime de nuevo la misma línea de estado para mostrar el estado actualizado
- Imprime
"XP to next level: <amount>" - Intenta cambiar el nombre a
"Al"(la validación debe fallar) - Imprime
"Name after invalid change: <name>" - Cambia el nombre a
"Champion"(debe funcionar) - Imprime
"Name after valid change: <name>"
- Crea un
La entrada de experiencia se proporcionará como una cadena que tendrás que convertir en un entero. Incluye el archivo de cabecera en main.cpp usando #include "Player.h".
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;
int main() {
// Leer el nombre del jugador
string playerName;
getline(cin, playerName);
// Leer los puntos de experiencia a añadir (como string, convertir a int)
string expString;
getline(cin, expString);
int expToAdd = stoi(expString);
// TODO: Crear un Player con el nombre de entrada
// TODO: Imprimir el estado inicial: "Player: <name>, Level: <level>, XP: <experience>"
// TODO: Añadir los puntos de experiencia de entrada usando addExperience()
// TODO: Imprimir la línea de estado actualizada
// TODO: Print "XP to next level: <amount>"
// TODO: Intentar cambiar el nombre a "Al" (debería fallar la validación)
// TODO: Print "Name after invalid change: <name>"
// TODO: Cambiar el nombre a "Champion" (debería tener éxito)
// TODO: Print "Name after valid change: <name>"
return 0;
}
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 OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genéricoPractica por tu cuenta: Compilador de C++ online