¡Hola! Me parece que andas usando un bloqueador de anuncios =( ¿Nos desbloqueas? ¿Por qué?
F13

Funcion 13

Orientación a objetos en PHP para principiantes

Llevo bastante tiempo queriendo hacer este artículo, especialmente habiendo introducido ya algunos de estos conceptos en otros artículos ya que no me gusta hablar de temas que no haya explicado antes.

Conozco a muchos programadores PHP a los que el concepto de la programación orientada a objetos les asusta. Yo he estado ahí. La sintaxis es distinta. Pero en este artículo intentaré que comprendas la programación orientada a objetos (OOP por sus siglas en inglés), un estilo de programación en el cual las acciones están agrupadas en clases que nos ayudan a crear código más compacto y fácil de  mantener.

La programación orientada a objetos nos permite agrupar tareas similares en clases. Esto nos ayuda a asegurarnos de que no repetimos código, lo cual es uno de los mantras de la programación.

Quizá te estés preguntando porqué es importante no repetir código. El motivo principal es, ayudar en la mantenibilidad del mismo. Imagina que tienes “algo” que se encarga de enviar correos a gente. Por el motivo que sea, tienes que añadir a alguien con copia oculta para que puedan ver qué correos se están enviando. ¿Te imaginas tener ese “algo” repartido por muchos sitios de la aplicación y tener que cambiarlo en todos sitios? No mola.

La programación orientada a objetos es algo que siempre intimida al principio, así que vamos a ir despacito, cogidos de la mano.. ¡No te pierdas!

De Objetos y Clases

Empezamos con algo suavito. ¿Qué es un objeto? ¿Qué es una clase? ¿Son lo mismo? ¿En qué se parecen y diferencian?

Una clase es algo conceptual, es la definición, más bien la base de los objetos. Las clases definen las propiedades y los métodos que luego podrán usar los objetos. En términos de una aplicación, usaremos un usuario. Sabemos que un usuario va a tener, por ejemplo, un valor usuario y otro valor password así como un método para hacer login.

El objeto, por otro lado, es la usuario en sí que se ajusta a lo que hemos definido en la clase. Por tanto, tenemos al usuario juan con contraseña 01juan01 y sabemos que puede hacer login. Se dice que juan es una instancia del objeto Usuario. Podemos tener cienes y cienes de usuarios, pero sabemos que todos ellos tienen lo mismo.

Ahora en PHP

Crear una clase en PHP es bastante sencillo y no difiere mucho a como se hace en otros lenguajes de programación:

class Usuario { }

Ahora veamos cómo podemos crear a juan. Solo tendremos que valernos de la palabra clave new.

$juan = new Usuario;

Por ahora fácil, ¿no?

Añadiendo propiedades

Una propiedad no es más que una variable, y la usaremos para guardar información sobre el objeto en sí. Veamos cómo añadir nuestras propiedades.

class Usuario { 
  public $usuario;
  public $password;
}

En seguida veremos qué es public. Por ahora quédate con que la propiedad es pública lo cual quiere decir que cualquiera puede acceder a ella. Después de public, tenemos el nombre de la propiedad.

Veamos cómo escribir y leer estas propiedades.

class Usuario { 
  public $usuario; 
  public $password; 
} 

$juan = new Usuario; 
$juan->usuario = 'juan'; 
$juan->password = '01juan01'; 
echo $juan->usuario; // juan

Si te fijas, estamos usando $juan->[nombre_propiedad]. Quizá te estés preguntando… ¿por qué no puedo hacer algo así? Usuario->usuario. La respuesta es, que puede haber un número indeterminado de usuarios y, el valor 01juan01 está dentro del objeto, no de la clase.

Añadiendo métodos

Añadir métodos es tan sencillo como añadir propiedades. Vamos a añadir un método para saludar.

class Usuario {
    public $usuario;
    public $password;
    public function saludar() {
        echo '¡Hola ' . $this->usuario . '!';
    }
}

Lo primero que te estarás preguntando es… ¿qué es $this? $this es la forma que tienen los objetos de referirse a sí mismos. Por ende, para poder acceder al valor de $usuario desde el propio objeto, tendremos que valernos de $this.

Llamar al método no tiene mucho misterio:

$juan = new Usuario;
$juan->usuario = 'juan';
$juan->saludar(); // ¡Hola juan!

Ahora, si usamos varios objetos, podemos almacenar valores distintos en ellos y llamar a sus métodos:

$usuarios = null;
$usuarios[] = new Usuario;
$usuarios[] = new Usuario;
$usuarios[0]->usuario = 'juan';
$usuarios[1]->usuario = 'manolo';
foreach ($usuarios as $usuario) {
    $usuario->saludar();
} // '¡Hola juan!' // '¡Hola manolo!'

Métodos mágicos

PHP nos ofrece una serie de métodos mágicos que son llamados cuando realizamos ciertas acciones con el objeto, como por ejemplo cuando un objeto es creado. Esto nos ayuda a automatizar trabajo en ciertas ocasiones.

Constructores y destructores

Cuando una clase se crea o se destruye, se llama a unos métodos mágicos como ya hemos adelantado. Si queremos realizar alguna acción en cualquiera de los dos eventos, tendremos que definir esos métodos e implementar su funcionalidad.

El método __construct() se llama cuando creamos una clase y suele ser un buen punto para rellenar información por defecto, o formar un objeto con algo que venga de la base de datos, etc.

class Usuario {  
    public $usuario;
    public $password;
    public function __construct() {
        $this->password = '1234'; //Seguridad al poder! 
    } 
} 
$usuario = new Usuario; 
echo $usuario->password; // 1234  

Cabe destacar que podemos pasar datos al constructor:

class Usuario { public $usuario; public $password; public function __construct($usuario) { $this->password = '1234'; $this->usuario = $usuario; } } $usuario = new Usuario('juan'); echo $usuario->usuario; // juan

Por otro lado, el destructor se llama cuando la clase es destruida. Esto ocurre automáticamente cuando PHP termina de ejecutarse, libera todos los recursos que tenga asociados y va llamando al método __destruct() de todas las clases en caso de que lo tengan. También podemos forzarlo usando la función unset sobre el objeto. En el destructor se suelen implementar cierres de conexiones a bases de datos, liberación de memoria, etc.

Veámoslo en un breve ejemplo:

class Usuario {  
    public $usuario;
    public $password;
    public function __construct($usuario) {
        $this->password = '1234';
        $this->usuario = $usuario;
    }
    public function __destruct() {
        echo 'Muero...';
    }
}
$usuario = new Usuario('juan');
unset($usuario); // 'Muero...';  

Nota: Existen más métodos mágicos que he obviado porque no los considero importantes para un curso básico de orientación a objetos. No obstante si eres curioso o quieres saber más, no dejes de echarle un vistazo a la documentación oficial.

Herencia de clases

Aquí es donde veremos uno de los aspectos más potentes de la orientación a objetos. Una clase puede heredar propiedades y métodos de otra clase. Esto es útil cuando quieres añadir funcionalidad a una clase ya existente.

Siguiendo nuestro ejemplo, nuestra clase padre es Usuario y ahora, vamos a crear una clase hija que sea Administrador.

class Usuario {  
    public $usuario;
    public $password;
    public function saludar() {
        echo 'Hola ' . $this->usuario;
    }
}
class Administrador extends Usuario {  
    public function banear($usuario) {
        echo $usuario->usuario . " ha sido baneado";
    }
}
$usuario = new Usuario;
$usuario->usuario = 'juan';
$admin = new Administrador;
$admin->usuario = 'Súper López';
$admin->saludar(); // Hola Súper López 
$admin->banear($usuario); // juan ha sido baneado

Usando la palabra clave extends, la clase Administrador ha heredado las propiedades usuario y password y el método saludar y hemos añadido un nuevo método banear a esta clase extendiendo las funcionalidades básicas de un usuario. Quizá el ejemplo sea muy absurdo pero tened en cuenta que podemos querer implementar funciones más complejas como login, logout, etc. y de esta forma nos acabamos ahorrando muchísimo código.

¿Qué pasaría si quiero que saludar sea distinto en el Administrador?

Sobreescribiendo métodos

Sobreescribir un método es tan sencillo como… ¡volverlo a definir! En la clase hija, volvemos a definir el método saludar.

class Usuario {  
    public $usuario;
    public $password;
    public function saludar() {
        echo 'Hola ' . $this->usuario;
    }
}
class Administrador extends Usuario {  
    public function saludar() {
        echo 'Hola admin>> ' . $this->usuario;
    }
    public function banear($usuario) {
        echo $usuario->usuario . " ha sido baneado";
    }
}
$admin = new Administrador;
$admin->usuario = 'Súper López';
$admin->saludar(); // Hola admin>> Súper López

Si además queremos mantener la funcionalidad original, podemos hacerlo llamando a la función del padre:

class Usuario {  
    public $usuario;
    public $password;
    public function saludar() {
        echo 'Hola ' . $this->usuario;
    }
}
class Administrador extends Usuario {  
    public function saludar() {
        echo '¡';
        parent::saludar();
        echo '!';
    }
    public function banear($usuario) {
        echo $usuario->usuario . " ha sido baneado";
    }
}
$admin = new Administrador;
$admin->usuario = 'Súper López';
$admin->saludar(); // ¡Hola Súper López!

Como verás, hemos mezclado funcionalidades de ambos métodos.

Visibilidad de métodos y propiedades

Hasta ahora tanto las propiedades como los métodos que hemos vistos, eran todos public. Ahora vamos a ver qué significa eso y el resto de tipos que tenemos.

public

A los métodos y propiedades public, se puede acceder desde cualquier sitio. Tanto dentro de la clase como fuera.

protected

Cuando declaramos una propiedad o método como protected, solo podremos accederlos desde la propia clase o sus descendientes (las clases hijas).

private

Los métodos y propiedades private solo pueden ser leídos dentro de la propia clase que lo define. Este breve ejemplo nos muestra lo que pasaría:

class Usuario {  
    public $usuario;
    private $password;
}
$usuario = new Usuario;
$usuario->password = 'Argofifa'; // <-- ERROR!

Clases y métodos estáticos

Las clases y métodos estáticos pueden ser de cualquiera de los tipos anteriores, public, protected o private pero tienen la peculiaridad de que no requieren que la clase sea instanciada. Además, las propiedades estáticas guardan el valor durante la ejecución del script. Veamos un breve ejemplo:

<?php  
class Usuario {  
    public $usuario;
    public $password;
    public static $contador = 0;
    public function __construct() {
        self::$contador++;
    }
}
$usuario1 = new Usuario;
echo Usuario::$contador; // 1  
$usuario1 = new Usuario; 
echo Usuario::$contador; // 2  
?>

Ten en cuenta, que cuando nos referimos a una propiedad o método estático, no podremos hacer uso de $this, pero tendremos acceso a self, que viene a ser lo mismo solo que únicamente podremos usar métodos y propiedades estáticas. Puedes llamar a métodos y usar propiedades estáticas desde un método público pero no al contrario.

Y hasta aquí … por ahora. Ahora mismo tendrías que tener una idea más clara del estilo de programación con objetos. Te recomiendo que empieces a probar por tu cuenta y, si tienes dudas, vengas y las comentes. Aprender la programación orientada a objetos es uno de los pasos importantes de la vida de todo programador. Cuando se lleva a cabo de la forma adecuada, el código producido será más fácil de leer, de mantener e incluso podrás compartir clases entre distintas aplicaciones ya que una clase solo debe contener código relacionado con su propia clase.

En algún momento del futuro lejano publicaré un artículo sobre la metodología MVC, otro de los grandes escollos con los que nos encontramos en nuestra carrera de programadores.

¿Crees que hay algo que se haya quedado por explicar? ¿Algún punto que no entiendas? ¿Ya usas la orientación a objetos y crees que podrías dar algún consejo a un principiante? ¡Ánimo! Déjanos un comentario.

Programador Front-end en First + Third y Potato. Trabajando con JavaScript y HTML5 desde el corazón de Sevilla.

Comentarios ¡Únete a la conversación!