Ocultamiento de información
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 41 de 91.
Ocultamiento de información es el principio detrás del encapsulamiento: la idea de que una clase debe exponer solo lo que es necesario y ocultar sus detalles de implementación interna. Si bien los modificadores de acceso y los getters/setters son las herramientas, el ocultamiento de información es la filosofía de diseño que guía cómo usarlos.
El objetivo es crear un límite claro entre lo que hace una clase (su interfaz pública) y cómo lo hace (su implementación interna). Esta separación significa que puedes cambiar el funcionamiento interno sin afectar al código que utiliza la clase:
<?php
class Temperature {
private float $celsius;
public function setCelsius(float $value): void {
$this->celsius = $value;
}
public function getCelsius(): float {
return $this->celsius;
}
public function getFahrenheit(): float {
return ($this->celsius * 9/5) + 32;
}
}
$temp = new Temperature();
$temp->setCelsius(25);
echo $temp->getCelsius() . "C = " . $temp->getFahrenheit() . "F";
Salida:
25C = 77FLa clase almacena la temperatura internamente en Celsius, pero los usuarios no necesitan saber esto. Podrías cambiar más tarde el almacenamiento interno a Fahrenheit o Kelvin y, mientras los métodos públicos sigan funcionando de la misma manera, ningún código externo se romperá.
Punto clave: El ocultamiento de información protege su código de los cambios. Oculte los detalles de implementación, exponga solo interfaces estables y sus clases serán más fáciles de mantener y modificar con el tiempo.
Desafío
FácilVamos a construir un conversor de divisas que demuestre la ocultación de información en acción. Crearás una clase que almacena dinero internamente en una divisa pero que puede convertir sin problemas desde y hacia múltiples divisas, sin que el código externo sepa nunca cómo se almacenan realmente los datos.
Organizarás tu código en dos archivos:
Money.php— Crea una claseMoneyque almacene internamente todos los montos en centavos (como un entero) para evitar problemas de precisión de punto flotante. Este detalle de implementación debe estar completamente oculto para los usuarios de la clase. La clase debe proporcionar:- Una propiedad privada para almacenar el monto en centavos
setDollars(float $amount)— acepta un monto en dólares y lo almacena internamente como centavosgetDollars()— devuelve el monto en dólares (float, 2 decimales)setEuros(float $amount)— acepta euros y los convierte a centavos usando la tasa: 1 EUR = 1.10 USDgetEuros()— devuelve el monto convertido a euros (float, 2 decimales)getInternalValue()— devuelve el valor bruto en centavos (entero) para fines de depuración
main.php— Incluye el archivo Money. Recibirás dos entradas: un monto en dólares y un monto en euros. Crea una instancia deMoney. Primero, establece el monto en dólares (convertido a float) e imprime tres líneas: el valor en dólares, el equivalente en euros y el valor interno en centavos. Luego, establece el monto en euros (convertido a float) e imprime los mismos tres valores nuevamente.
La belleza de este diseño es que el código externo trabaja con valores familiares en dólares y euros, sin saber en absoluto que todo se almacena internamente como centavos. Más adelante podrías cambiar el almacenamiento interno para usar una divisa base diferente o una estrategia de precisión distinta, y mientras los métodos públicos sigan funcionando correctamente, no sería necesario cambiar ningún código externo.
Formatea todas las salidas de dólares y euros a exactamente 2 decimales. Cada valor debe imprimirse en su propia línea, lo que resulta en un total de seis líneas de salida.
Hoja de referencia
El ocultamiento de información es el principio detrás del encapsulamiento: exponer solo lo necesario mientras se ocultan los detalles de la implementación interna. Esto crea un límite claro entre lo que hace una clase (interfaz pública) y cómo lo hace (implementación interna).
Ejemplo de ocultamiento de información con una clase Temperature:
<?php
class Temperature {
private float $celsius;
public function setCelsius(float $value): void {
$this->celsius = $value;
}
public function getCelsius(): float {
return $this->celsius;
}
public function getFahrenheit(): float {
return ($this->celsius * 9/5) + 32;
}
}
$temp = new Temperature();
$temp->setCelsius(25);
echo $temp->getCelsius() . "C = " . $temp->getFahrenheit() . "F";
// Salida: 25C = 77F
La clase almacena la temperatura internamente en Celsius, pero los usuarios no necesitan saber esto. El almacenamiento interno podría cambiarse a Fahrenheit o Kelvin sin romper el código externo, siempre que los métodos públicos sigan funcionando de la misma manera.
Beneficios clave: El ocultamiento de información protege el código de los cambios. Al ocultar los detalles de implementación y exponer solo interfaces estables, las clases se vuelven más fáciles de mantener y modificar con el tiempo.
Pruébalo tú mismo
<?php
require_once 'Money.php';
// Leer entradas
$dollarAmount = floatval(trim(fgets(STDIN)));
$euroAmount = floatval(trim(fgets(STDIN)));
// TODO: Crear una instancia de Money
// TODO: Establecer la cantidad en dólares e imprimir:
// - El valor en dólares (2 decimales)
// - El equivalente en euros (2 decimales)
// - El valor interno en centavos (entero)
// TODO: Establecer la cantidad en euros e imprimir:
// - El valor en dólares (2 decimales)
// - El equivalente en euros (2 decimales)
// - El valor interno en centavos (entero)
?>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 externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy