13. Objetos
Con el lanzamiento de PHP 5 se añadió soporte para la Programación Orientada a Objetos (POO). Antes de continuar quiero que sepas que existen 3 paradigmas o formas de organizar su código:
- Estructurada: Tal como hemos trabajado hasta ahora. Las instrucciones siguen un orden del principio del archivo hasta el final.
- Funcional: funciones que llaman a otras funciones (declaradas o anónimas). Su potencial radica en que se evitan muchos errores. Existen lenguajes mejores que PHP para este fin (Lisp, Elixir, Haskell...).
- Objetos: Encapsular variables y funciones.
Los objetos nos permiten mantener en un mismo sitio una gran cantidad de variables y funciones que se pueden fusionar con otros lugares. Tranquilo que no busco que los manejes como un experto pero si que seas capaz de interpretar y crear unos objetos simples.
Clase
En el ejemplo tenemos un objeto que lo hemos llamado Gato. Dentro contiene una variable y una función.
// Declaración
class Gato
{
// Variables publicas
public $nombre = 'Felix';
/**
* Método para escuchar al gato
* @return void
*/
public function maullar(): void
{
echo 'Miiiiauuuu';
}
}
Para utilizarlo se debes instanciarlo. Para ello existe una palabra reservada llamada new.
// Se instancia el objeto Gato
$miGato = new Gato();
Ahora ya se puede utilizar su interior con las flechas ->.
// Se llama a la funcion de Gato
$miGato->maullar();
// echo: Miiiiauuuu
echo $miGato->nombre;
// echo: Felix
Constructor
Los constructores son las funciones que serán ejecutadas al crear el objeto.
Por ejemplo.
// Declaración
class Gato
{
// Variables publicas
public $nombre = 'Felix';
/**
* Método para escuchar al gato
* @return void
*/
function __construct()
{
echo 'Miiiiauuuu';
}
}
new Gato();
// Miiiiauuuu
Uno de sus usos más extendido es definir sus valores al crear el objeto.
// Declaración
class Gato
{
// Variables publicas
public string $nombre = '';
/**
* @return void
*/
function __construct(string $nombre)
{
$this->nombre = $nombre;
}
}
$miGato = new Gato('Federico');
echo $miGato->nombre;
// Federico
Puede ser resumida con la siguiente estructura.
// Declaración
class Gato
{
/**
* @return void
*/
function __construct(public string $nombre = '')
{
// Nada que hacer, tómate un descanso
}
}
$miGato = new Gato('Gustavo');
echo $miGato->nombre;
// Gustavo
Constructor Property Promotion (PHP 8.0+): Esta sintaxis compacta se llama "promoción de propiedades del constructor". Permite declarar y asignar propiedades directamente en la firma del constructor, ahorrando código repetitivo. Es especialmente útil cuando tienes muchas propiedades que solo necesitas inicializar.
Además podemos disponer de varios constructores que hagas diferentes funciones.
// Declaración
class Gato
{
// Variables publicas
public string $nombre = 'Felix';
/**
* Método para escuchar al gato
* @return void
*/
function __construct(...$args)
{
if (isset($args[0])) {
$this->nombre = $args[0];
echo 'Hola ' . $this->nombre;
} else {
echo 'Miiiiauuuu';
}
}
}
$miGatoFavorito = new Gato();
// Miiiiauuuu
echo $miGatoFavorito->nombre;
// Felix
$miGatoTalVezVivo = new Gato('Schrodinger');
// Hola Schrodinger
echo $miGatoFavorito->nombre;
// Schrodinger
Propiedades de solo lectura (PHP 8.1+)
Las propiedades readonly se pueden inicializar una sola vez y no se pueden modificar después. Son perfectas para valores que no deben cambiar después de la construcción del objeto.
class Usuario
{
public function __construct(
public readonly string $id,
public readonly string $email,
public string $nombre
) {}
}
$usuario = new Usuario('123', 'usuario@ejemplo.com', 'Ana');
echo $usuario->id;
// 123
// Esto está permitido
$usuario->nombre = 'María';
// Esto lanzará un error
$usuario->id = '456';
// Error: Cannot modify readonly property Usuario::$id
Ventajas de readonly: - Mayor seguridad, evita modificaciones accidentales. - Código más claro al indicar qué valores son inmutables. - Útil para DTOs (Data Transfer Objects) y Value Objects.
Enumeraciones (PHP 8.1+)
Las Enumeraciones (Enums) permiten definir un tipo con un conjunto fijo de valores posibles. Son ideales para representar estados, roles, categorías o cualquier valor que tenga opciones limitadas.
// Enum básico (backed por strings)
enum Estado: string
{
case PENDIENTE = 'pendiente';
case APROBADO = 'aprobado';
case RECHAZADO = 'rechazado';
}
// Uso
function procesarPedido(Estado $estado): void
{
echo match($estado) {
Estado::PENDIENTE => 'El pedido está pendiente de revisión',
Estado::APROBADO => 'El pedido ha sido aprobado',
Estado::RECHAZADO => 'El pedido ha sido rechazado',
};
}
procesarPedido(Estado::APROBADO);
// El pedido ha sido aprobado
// Enum con métodos
enum Rol: string
{
case ADMIN = 'admin';
case EDITOR = 'editor';
case VIEWER = 'viewer';
public function puedeEditar(): bool
{
return match($this) {
self::ADMIN, self::EDITOR => true,
self::VIEWER => false,
};
}
public function descripcion(): string
{
return match($this) {
self::ADMIN => 'Administrador con todos los permisos',
self::EDITOR => 'Puede editar contenido',
self::VIEWER => 'Solo puede ver contenido',
};
}
}
$rol = Rol::EDITOR;
echo $rol->descripcion();
// Puede editar contenido
var_dump($rol->puedeEditar());
// bool(true)
Ventajas de los Enums: - Código más seguro y autodocumentado. - Previene valores inválidos. - El IDE puede autocompletar los valores posibles. - Permite asociar métodos y comportamientos a los valores.
Visibilidad
Una de las características más importantes de los objetos es la visibilidad, o los permisos que puede tener las variables o funciones. Similar a dar privilegios de acceso.
Las posibilidades son:
- public: cualquier puede usarlo.
- private: solo es accesible desde el propio objeto.
- protected: solo es accesible desde el propio objeto o herederos.
Si no se indica lo contrario será public.
/**
* Definición de Amigo
*/
class Amigo
{
// Declaración de un constructor public
public function __construct() { }
// Declaración de un método public
public function MyPublic() { }
// Declaración de un método protected
protected function MyProtected() { }
// Declaración de un método private
private function MyPrivate() { }
// Esto es public
function tomarCerveza()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
Herencia
Es posible instanciar un objeto y fusionar las variables y las funciones del otro objeto ya instanciado. Para ello se utiliza la palabra reservada extends.
// Hereda todo el objeto de Gato
class Garfield extends Gato {
// Variables publicas
public $nombre = 'Garfield';
/**
* Método para expresar la comida favorita
* @return void
*/
public function comidaFavorita(): void
{
echo 'Lasaña';
}
}
Instanciamos nuestro gato Garfield.
// Se instancia el objeto Garfield
$miGatoComilon = new Garfield();
Y ya podemos usar todas las variables y funciones tanto de Gato como de Garfield. Pero... ¿que pasa con la variable que tiene el mismo nombre ($nombre)? Como Garfield es el hijo sobrescribe por su valor.
// Se llama a la funcion de Gato
$miGatoComilon->maullar();
// echo: Miiiiauuuu
// Se llama a la funcion de Garfield
$miGatoComilon->comidaFavorita();
// echo: Lasaña
echo $miGatoComilon->nombre;
// echo: Garfield
Se nos queda por el camino muchos conceptos que no veremos.
- Sobrecarga.
- Estáticos.
- Interfaces.
- Abstración.
- Rasgos (Traits).
- ...
Por ahora lo dejaremos aquí, no es necesario profundizar mucho más mientras sepamos utilizarlos.
Actividad 1
Crea un objeto llamado Cuenta para un banco con las siguientes necesidades.
- Variables: nombre, apellidos, DNI, saldo y activa.
- Funciones: actualizar datos del cliente, ingresar dinero, restar dinero, bloquear, desbloquear, mostrar información del cliente.
Prueba todas las posibilidades.
Actividad 2
Crea un objeto llamado Habitación para una cadena de Hoteles con las siguientes necesidades.
- Variables: numero, camas, disponible, limpia y capacidad.
- Funciones: actualizar datos de la habitación, marcar como sucia, marcar somo limpia, marcar como disponible, marcar como ocupada, ver capacidad y ver número.
Prueba todas las posibilidades.
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Desafíos de programación atemporales y multiparadigmáticos
Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.
Buy the book
Support me on Ko-fi
Comments
There are no comments yet.