Herramientas de usuario

Herramientas del sitio


informatica:programacion:programacion_orientada_a_objetos:php

¡Esta es una revisión vieja del documento!


Programación Orientada a Objetos en PHP

Notas sobre el uso de Programación Orientada a Objetos en PHP.

PHP incluye soporte para Programación Orientada a Objetos desde la versión 5.0

includes a complete object model. Some of its features are: visibility, abstract and final classes and methods, additional magic methods, interfaces, and cloning.

PHP treats objects in the same way as references or handles, meaning that each variable contains an object reference rather than a copy of the entire object. See Objects and References

Crear una clase

Para definir una clase se utiliza la palabra reservada class seguida del nombre de la clase, seguido de llaves que encerrará la definición de propiedades y métodos pertenecientes a dicha clase:

class Persona {
 
    // Propiedades
 
    // Métodos
 
}

El nombre de la clase sigue las normas de nombrado de PHP: puede empezar con una letra o guion bajo seguido de cualquier número de letras, números o guiones bajos.

Crear un método

Igual que las funciones, para definir un método se utiliza la palabra reservada function:

class Persona {
 
    function hablar() {
        echo "Hola!";
    }
}

Crear una instancia

Instanciar una clase es crear un objeto. El objeto tendrá las propiedades y métodos definidos en la clase.

Para crear una instancia utilizamos la palabra reservada new.

class Persona {
    function hablar() {
        return "Hola";
    }
}
 
// Creación de instancias
$fulanito = new Persona();
$menganito = new Persona();

Para llamar a un método utilizamos el operador :

echo "Fulanito dice: " . $fulanito->hablar();
echo "Menganito dice: " . $menganito->hablar();

Crear propiedades

Las propiedades son las variables propias de una clase.

class Persona {
 
  public $nombre;
  public $edad;
 
}

En versiones antiguas de PHP se usaba la palabra reservada var antes de declarar las propiedades.

Si declaramos una propiedad sin un modificador de visibilidad/acceso, esta será declarada como public.

Para acceder a las propiedades se usa el operador .

$fulanito = new Persona();
$fulanito->nombre = "Fulanito";
$fulanito->edad = "18";

Por medio de $this podemos hacer referencia a las propiedades y métodos dentro de la propia clase.

class Persona {
 
  public $nombre;
  public $edad;
 
  function hablar() {
      return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
  }
 
}

Crear un constructor

Un constructor es una función que se ejecuta cuando se crea un objeto, así que es útil para recibir parámetros iniciales o ejecutar acciones o métodos cuando se “construye” el objeto. El constructor es la palabra reservada __construct:

class Persona {
 
    private $nombre;
    private $edad;
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre
        $this->edad = $edad;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
    }
}

Cuando creemos el objeto, podremos indicarle los parámetros:

$fulanito = new Persona("Fulanito", 18);
 
echo $fulanito->hablar();

Promocionar las propiedades del constructor

Antes de la versión 8, los parámetros del constructor se definen primero dentro de la clase, luego dentro del constructor y finalamente se asignan unos a otros:

class Punto {
    public float $x;
    public float $y;
    public float $z;
 
    public function __construct(float $x = 0, float $y = 0, $z = 0) {
       $this->x = $x;
       $this->y = $y;
       $this->z = $z;
    }
}

Desde PHP 8 podemos abreviar:

class Punto {
 
    public function __construct(public float $x = 0, public float $y = 0, public $z = 0) {
       $this->x = $x;
       $this->y = $y;
       $this->z = $z;
    }
}

Crear una función destructora

Generalmente no sería necesario encargarse de destruir un objeto cuando no se usa ya que este trabajo es automático por parte del recolector de basura de PHP. Una función destructura se ejecuta cuando el objeto deja de existir, ya sea porque termina el script o porque usamos la función unset(). La función destructora en PHP es __destruct:

class Persona {
 
    private $nombre;
    private $edad;
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre
        $this->edad = $edad;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
    }
 
    function __destruct() {
        echo $this->nombre . " me suicido";
    }
 
}

Cuando creemos el objeto, al terminar nuestro script veremos qué sucede:

$fulanito = new Persona("Fulanito", 18);
 
echo $fulanito->hablar();
 
// Ahora se mostrará por pantalla: "Fulanito se suicida"

Si queremos forzar la destrucción del objeto en cualquier momento del script, usamos la función unset():

$fulanito = new Persona("Fulanito", 18);
 
echo $fulanito->hablar();
 
unset($fulanito);
 
// Ahora se mostrará por pantalla: "Fulanito se suicida"

Herencia

Se trata de uno de los pilares de la programación orientada a objetos. Con la herencia se crea la jerarquía de clases.

En PHP se realiza con la palabra reservada extends:

class Trabajador extends Persona {
}

La clase Trabajador hereda todo lo que tenga la clase Persona:

$benito = new Trabajador("Benito", 20);
echo $benito->hablar();

Modificadores de acceso

Un concepto fundamental en la Programación Orientada a Objetos es el encapsulamiento, es decir, que dentro de una clase vayan tanto datos como acciones. De esta manera, otro usuario (desarrollador u otro código) solo podrá tener acceso a lo que nosotros queramos, todo lo demás estará “encapsulado” o restringido.

Los modificadores de acceso permiten definir qué propiedades y métodos se podrán usar desde otras clases o scripts. En PHP tenemos los siguientes:

  • public: acceso total. Es el valor por defecto si no se indica.
  • private: solo acceso desde dentro de la clase.
  • protected: acceso dentro de la clase y dede de las heredadas.
class Persona {
 
    private $nombre;
    private $edad;
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre
        $this->edad = $edad;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
    }
}

Tras haber definido las propiedades como privadas, no podríamos hacer lo siguiente:

$fulanito = new Persona("Fulanito", 18);
echo $fulanito->edad; // Esto no funcionaría porque no tenemos acceso desde fuera de la clase

El error sería algo como:

Fatal error: Cannot access private property Persona::$edad in Persona.php on line XXX

Para limitarlo a las clases heredadas, usamos protected:

class Persona {
 
    protected $nombre;
    protected $edad;
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre
        $this->edad = $edad;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
    }
}

En la clase heredada:

class Trabajador extends Persona {
    public function hablarTrabajador() {
        return "Soy trabajador y tengo " . $this->edad . "años";
    }
 
}

Pero si hubiésemos definido las propiedades de la clase Persona como private, al hacer esto:

$fulanito = new Trabajador("Fulanito", 18);
 
echo $fulanito->hablarTrabajador();

Obtendríamos un error al acceder a la propiedad edad:

Notice: Undefined property: Trabajador::$edad in Trabajador.php on line XX

Setters y getters

Otra herramienta que nos permite manejar el encapsulamiento de las clases es realizar las funciones getters y setters que no es más que funciones que manipularán las propiedades de la clase. Las propiedades siempre deberían estar como privadas o protegidas para evitar que se acceda accidental o intencionalmente desde el exterior.

class Persona {
    protected $nombre;
    private $edad;
    private $corbata = "No";
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre
        $this->edad = $edad;
    }
 
    // Setter
    public function set_corbata($corbata) {
        $this->corbata = $corbata;
    }
 
    // Getter
    public function get_corbata() {
        return $this->corbata;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años";
    }    
 
    public function tiene_corbata() {
        return $this->nombre " " . $this->corbata . " tiene corbata";
    }
}

Los usamos:

$fulanito = new Persona("Fulanito", 18);
$fulanito->set_corbata("Sí");
echo $fulanito->tiene_corbata();
// Devolverá:
// Fulanito Sí tiene corbata

Métodos mágicos

Los métodos mágicos son un tipo especial de métodos que sobrescriben la acción por defecto de PHP cuando se realizan ciertas acciones sobre un objeto.

__set y __get

  • __set: permite escribir datos sobre propiedades inaccesibles (protegidas o privadas).
  • __get: Permite consultar datos sobre propiedades inaccesibles (protegidas o privadas)

PHP reserva los dos guiones bajos seguidos para los métodos mágicos. __construct y __destruct son también métodos mágicos

class Persona {
 
    private $nombre;
    private $edad;
    private $corbata = "no";
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre;
        $this->edad = $edad;
    }
 
    public function __destruct() {
        echo $this->nombre . " se suicida";
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años" . PHP_EOL;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __set($name, $value) {
        $this->$name = $valor;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __get($name) {
        return $this->$name;
    }
 
    public function set_corbata($corbata) {
        $this->corbata = $corbata;
    }
 
    public function get_corbata() {
        return $this->corbata;
    }
 
    public function tiene_corbata() {
        return $this->nombre . " " . $this->corbata . " tiene corbata";
    }
}

Para usarlo:

$fulanito = new Persona("Fulanito", 18);
//$fulanito->set_corbata("Sí");
$fulanito->corbata = "No";
echo $fulanito->tiene_corbata();

Pudimos cambiar la propiedad privada sin problema.

Con el __set podríamos hacer la modificación de cualquiera de las propiedades:

$fulanito = new Persona("Fulanito", 18);
$fulanito->corbata = "No";
$fulanito->nombre = "Menganito";
$fulanito->edad = 20;

Conversión de una clase a cadena (__toString)

Por medio de la función __toString() podemos tener una cadena como salida de una instancia de una clase.

class Gato {
 
    private $nombre;
    private $pelo;
 
    public function __construct($nombre, $pelo) {
 
        $this->nombre = $nombre;
        $this->pelo = $pelo;
    }
 
    public function __toString() {
        return "Mi nombre es " . $this->nombre . " y el color de mi pelo es " . $this->pelo;
    }
}
$benito = new Gato("Benito", "azul");
 
echo $benito; // Mostrará "Mi nombre es benito y el color de mi pelo es azul"

Métodos y propiedades estáticas

Un modificador de acceso de mucha utilidad es static que permite utilizar métodos y propiedades sin necesidad de crear instancias de la clase.

El operador de resolución de ámbito / alcance (::) permite acceder a elementos estáticos, constantes y sobrescribir propiedades o métodos de una clase.

class Persona {
 
    public static $clave = "12345";
    private $nombre;
    private $edad;
    private $corbata = "no";
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre;
        $this->edad = $edad;
    }
 
    public function __destruct() {
        echo $this->nombre . " se suicida";
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años" . PHP_EOL;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __set($name, $value) {
        $this->$name = $value;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __get($name) {
        return $this->$name;
    }
 
    public function set_corbata($corbata) {
        $this->corbata = $corbata;
    }
 
    public function get_corbata() {
        return $this->corbata;
    }
 
    public function tiene_corbata() {
        return $this->nombre . " " . $this->corbata . " tiene corbata";
    }
}

Sin instanciar la clase (crear el objeto), podremos acceder a la propiedad estática

echo "La clave secreta es " . Persona::$clave";

Lo mismo pasaría con los métodos estáticos:

class Persona {
 
    // Atributos
 
    // Métodos
    public static function mensaje_secreto() {
        return "Haz el bien sin mirar a quien";
    }
}

Usamos:

echo "La frase secreta es " . Persona::mensaje_secreto();

Operador de resolución de alcance

Este operador nos permite acceder a métodos y propiedades estáticas.

  • self: sustituye a $this cuando llamamos a propiedades estáticas.
  • parent: la utilizamos cuando queremos llamar desde la clase hija las propiedades o métodos de la clase padre.

self

class Persona {
 
    public static $clave = "12354";
    private $nombre;
    private $edad;
    private $corbata = "no";
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre;
        $this->edad = $edad;
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años; la clave secreta es " . $this->clave. PHP_EOL;
    }

PHP nos mostrará un error por haber utilizado $this→clave para acceder a una propiedad estática.

La solución es usar self:

    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años; la clave secreta es " . self::$clave. PHP_EOL;
    }

parent

Para el ejemplo de parent, vamos a coger una clase hija:

class Trabajador extends Persona {
    public function hablar() {
        parent::hablar(); // método hablar() de la clase padre
        return "Yo soy la clase hija";
    }
}

Constantes

El operador :: también nos permite acceder a constantes:

class Persona {
 
    const MAYORIA_EDAD = 18;
    public static $clave = "12354";
    private $nombre;
    private $edad;
    private $corbata = "no";
 
    // código
}

Y para llamar esa constante fuera de la clase:

echo "La mayoría de edad en España es a los " . Persona::MAYORIA_EDAD . " años";

Sobrescribir métodos (overriding)

Práctica muy común en la programación orientada a objetos. Al crear una nueva clase a partir de otra (herencia), podemos hacer 3 cosas:

  • Añadir nuevas propiedades y métodos.
  • Eliminar propiedades y métodos.
  • Modificar propiedades y métodos.

Partimos de una clase:

class Persona {
 
    public static $clave = "12354";
    private $nombre;
    private $edad;
    private $corbata = "no";
 
    public function __construct($nombre, $edad) {
        $this->nombre = $nombre;
        $this->edad = $edad;
    }
 
    public function __destruct() {
        echo $this->nombre . " se suicida";
    }
 
    public function hablar() {
        return "Me llamo " . $this->nombre . " y tengo " . $this->edad . " años" . PHP_EOL;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __set($name, $value) {
        $this->$name = $value;
    }
 
    // Ojo, lleva ''$'' la propiedad
    function __get($name) {
        return $this->$name;
    }
 
    public function set_corbata($corbata) {
        $this->corbata = $corbata;
    }
 
    public function get_corbata() {
        return $this->corbata;
    }
 
    public function tiene_corbata() {
        return $this->nombre . " " . $this->corbata . " tiene corbata";
    }
}

Creamos una clase hija:

class Trabajador extends Persona {
    // Estamos sobrescribiendo un método existente en la clase padre:
    public function hablar() {
        return "Soy el currante " . $this->nombre . " y tengo " . $this->edad . " años" . PHP_EOL;
    }
}

Al llamar al método hablar() usará el de la clase hija:

$fulanito = new Trabajador("Fulanito", 18);
echo $fulanito->hablar(); // Devuelve: Soy trabajador y tengo 18 años

Evitar sobrescritura

Por medio de la palabra reservada final evitamos que la clase derivada sobrescriba un método.

Una clase también puede ser final y no se permitirá que se extendiera o heredara a otra clase.

Esto normalmente no se usa mucho ya que uno de los objetivos de la programación orientada a objetos es que puedan trabajar varias personas sobre la misma base de código. Si impedimos que algunas clases interesantes se puedan heredar o sobrescribir sus métodos, acabaríamos muy probablemente duplicando código.

class Gato {
    public function maullar() {
        echo "Miau";
    }
 
    final public function ronronear() {
        echo "rrrrr";
    }
}

Clase heredada:

class GatoVolador extends Gato {
    public function ronronear() {
       echo "ronroneo";
    }
}

Y la usamos:

$gato = new GatoVolador();

Nos daría el siguiente error:

Fatal error: Cannot override final method Gato::ronronear() in Clase.php on line X

Clonar objetos

Cuando queremos duplicar un objeto, el operador de igualdad (=) no sirve porque copia la referencia al objeto.

// Copiar por valor
$a = 10;
$b = 10; // tanto $a como $b valdrán lo mismo, pero si se modifica $a, no afecta al valor de $b
 
// Copiar por referencia
$objeto1 = $objeto2;
$objeto1->setNombre("objetoUno");
echo $objeto1->getNombre();
echo $objeto2->getNombre(); // saldría lo mismo que en $objeto1
 
$objeto2->setNombre("objetoDos");
echo $objeto1->getNombre(); // saldría "objetoDos"
echo $objeto2->getNombre(); // saldría "objetoDos"

Para duplicar un objeto usamos la palabra reservada clone.

$fulanito = new Persona("Fulanito", 19);
$menganito = clone $fulanito;
$menganito->setNombre("Menganito");
 
echo $fulanito->getNombre(); // Fulanito
echo $menganito->getNombre(); // Menganito

Manejo de constantes en clases

  • Las constantes se diferencian de las variables en que no es necesario el símbolo de dólar para definirlas ni para usarlas.
  • El valor de una constante no puede ser una variable, función o expresión
  • El valor de la constante es la misma para todas las instancias, no se pueden modificar.

Recordamos que para llamar una constante dentro de una clase usamos self:

class Persona {
    const EDAD = 18;
 
    function edadPersona() {
        return self::EDAD
    }
}
$persona = new Persona();
echo "La mayoría de edad en España es " . Persona::EDAD;
echo "La mayoría de edad en España es " . $persona->edadPersona();

Manejo de clases en archivos externos

La práctica más común es tener un archivo por clase. Podemos llamarlas con los comandos include, include_once, require y require_once.

require_once "PersonaClass.php";
 
class Trabajador extends Persona {
 
    // Código
 
}

Carga automática de clases

Al crear un fichero por clase, cuando vamos a usar muchas, una de las mayores molestias es tener que hacer una larga lista de inclusiones al comienzo de cada script (uno por cada clase). A partir de la versión 5.0.0 de PHP se pueden hacer autocargas para evitar el uso de include y require.

La función spl_autoload_register() permite autocargar las clases que llamemos en nuestro programa:

spl_autoload_register(function ($nombre_clase) {
    require_once "clases" . DIRECTORY_SEPARATOR . $nombre_clase . '.php';
});
 
$persona = new Persona("Fulanito", 19);

Gracias a esto, cada vez que detecte el uso de new, PHP buscará y cargará la clase adecuada dentro de la carpeta clases.

La práctica recomendada sería ir cargando las clases que necesitemos en lugar de no tener el control

Crear clases abstractas

  • Las clases abstractas no pueden ser instanciadas.
  • Pueden declarar la existencia de los métodos, pero no su implementación.
  • Pueden contener métodos no abstractos, pero deben contener al menos un método abstracto.
  • Los métodos abstractos deben ser definidos en las clases heredadas, pero deben tener la misma visibilidad.
  • La implementación debe tener la misma “firma”: la declaración de tipos y el número de argumentos.
  • Las clases abstractas están implementadas desde la versión 5.4.0.

Las clases abstractas se suelen usar en proyectos grandes.

Para crear una clase abstracta se emplea la palabra reservada abstract:

abstract class Mamifero {
 
    // Método abstracto
    abstract public function saludo();
 
    // Método no abstracto
    public function maullar() {
        return "Miau, miau";
    }
 
}

Esta clase no la podemos instanciar, pero sí heredar:

require_once "Mamifero.php";
 
class Gato extends Mamifero {
 
    public function saludo() {
        return "Hola, mundo";
    }
 
}
$felix = new Gato();
echo "Saludo: " . $felix->saludo();
echo "Maullido: " . $felix->maullar();

Crear interfaces

  • Las interfaces permiten crear código con el cual especificar qué métodos deben ser implementados por una clase (prototipos) sin definir su implementación
  • Los métodos declarados en una interfaz deben ser públicos.
  • Las interfaces se definen con la palabra reservada interface.
  • Para implementar una interfaz desde una clase se utiliza la palabra reservada implements
  • Una clase puede implementar más de una interfaz si se desea.

Las interfaces se suelen usar en proyectos grandes

interface iMamifero {
 
    public function andar();
 
    public function ruido();
 
}

Implementamos un par de clases:

class Gato implements iMamifero {
 
    public function andar() {
        return "camina";
    }
 
    public function ruido() {
        return "miau, miau";
    }
}
class Delfin implements iMamifero {
 
    public function andar() {
        return "nada";
    }
 
    public function ruido() {
        return "iu, iu";
    }
}

Instanciamos:

$felix = new Gato();
$flipper = new Delfin();
 
echo "El gato " . $felix->andar() . " y dice " . $felix->ruido();
echo "El delfín" . $flipper->andar() . " y dice " . $flipper->ruido();

Iteración de objetos

Desde la versión 5 podemos iterar las propiedades visibles o públicas de una clase.

class Gato {
    public $peso = 10;
    private $genero = "M";
    protected $edad = 0;
 
    public function iteracion() {
        echo "Iteración dentro de la clase" . PHP_EOL;
        foreach ($this as $clave => $valor) {
            echo $clave . " -> " . $valor . PHP_EOL;
        }
    }
}

Creamos el objeto:

$gato = new Gato();
 
$gato->iteracion();

Nos devolverá algo como:

Iteración dentro de la clase
peso -> 10
genero -> M
edad -> 0

Como hemos visto, al hacer la iteración dentro de la clase no importa los modificadores de acceso que hayamos usado con las propiedades. Si la iteración la hacemos fuera de la clase:

$gato = new Gato();
 
echo "Iteración fuera de la clase" . PHP_EOL;
foreach ($gato as $clave => $valor) {
    echo $clave . " - > " . $valor . PHP_EOL;
}

Nos devolvería:

Iteración fuera de la clase
peso - > 10

Porque solo la propiedad peso es pública.

Comparación de objetos

Dos instancias de una clase son iguales si tienen los mismos atributos y valores (los valores se comparan con el operador de igualdad, =)

Cuando se utiliza el operador de identidad (===), las variables de un objeto son idénticas sí y solo sí hacen referencia a la misma instancia de la misma clase.

class Gato {
 
    public $bandera;
}
 
class Perro {
 
    public $bandera;
}

Comparamos:

$gato1 = new Gato();
$gato2 = new Gato();
$gato3 = $gato1; // copia por referencia
 
$perro1 = new Perro();
 
echo "Comparamos elementos de la misma clase" . PHP_EOL;
 
echo "gato1 == gato";
echo ($gato1 == $gato2) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 != gato";
echo ($gato1 != $gato2) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 === gato";
echo ($gato1 === $gato2) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 !== gato";
echo ($gato1 !== $gato2) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;

Resultado:

Comparamos elementos de la misma clase
gato1 == gato Verdadero
gato1 != gato Falso
gato1 === gato Falso
gato1 !== gato Verdadero

Compararemos elementos de la misma clase a la misma referencia:

echo "Compararemos elementos de la misma clase a la misma referencia:" . PHP_EOL;
 
echo "gato1 == gato3";
echo ($gato1 == $gato3) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 != gato3";
echo ($gato1 != $gato3) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 === gato3";
echo ($gato1 === $gato3) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
 
echo "gato1 !== gato3";
echo ($gato1 !== $gato3) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;

Resultado:

Compararemos elementos de la misma clase a la misma referencia:
gato1 == gato3 Verdadero
gato1 != gato3 Falso
gato1 === gato3 Verdadero
gato1 !== gato3 Falso

Finalmente, compararemos elementos de diferente clase (aunque tengan los mismos elementos):

echo "Compararemos elementos de distinta clase, pero mismas propiedades:" . PHP_EOL;
 
echo "gato1 == perro1";
echo ($gato1 == $perro1) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
echo "gato1 != perro1";
echo ($gato1 != $perro1) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
echo "gato1 === perro1";
echo ($gato1 === $perro1) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;
 
echo "gato1 !== perro1";
echo ($gato1 !== $perro1) ? " Verdadero" . PHP_EOL: " Falso" . PHP_EOL;

Resultado:

Compararemos elementos de la misma clase a la misma referencia:
gato1 == perro1 Falso
gato1 != perro1 Verdadero
gato1 === perro1 Falso
gato1 !== perro1 Verdadero

Clases anónimas

Las clases anónimas no tienen nombre. Disponibles desde la versión 7 de PHP.

Las clases anónimas son útiles para definir objetos sencillos y desechables.

$gato = new Class("Don Gato") { 
    private $nombre;
 
    public function __construct($nombre) {
        $this->nombre = $nombre;
    }
 
    public function getNombre() {
        return "Mi nombre es " . $this->nombre;
    }
};
 
echo $gato->getNombre(); // Mi nombre es Don Gato

Traits (rasgos)

Por medio de los traits podemos reducir las limitaciones de la herencia simple (solo se puede heredar una clase).

Podemos reutilizar código (conjuntos de métodos) sobre clases independientes o a jerarquía de clase diferentes.

Un rasgo o trait es similar a las clases, pero solo agrupa métodos específicos.

interface Animal {
    function nacer();
    function crecer();
    function reproducir();
    function morir();
}
 
abstract class Vertebrado implements Animal {
    private $huesos;
 
    public function getHuesos() {
        return $this->huesos;
    }
 
    public function nacer() {};
    public function crecer() {};
    public function reproducir() {};
    public function morir() {};
}
 
abstract class Invertebrado implements Animal {
    private $hemocianina;
 
    public function getHemocianina() {
        return $this->hemocianina;
    }
 
    public function nacer() {};
    public function crecer() {};
    public function reproducir() {};
    public function morir() {};
}
 
class Molusco extends Invertebrado {
 
    private $radula;
 
    public function getRadula() {
        return $this->radula;
    }
}
 
class Reptil extends Invertebrado {
 
    private $escamas;
 
    public function getEscamas() {
        return $this->escamas;
    }
}

Tanto los moluscos como los reptiles son ovíparos. Si creásemos una clase abstracta Ovíparo, no podríamos heredar de ella porque ya están heredando de Vertebrado y de Invertebrado (PHP solo permite herencia simple). Para este caso se usan los traits:

trait Oviparo {
 
    private $huevos;
 
    public function getHuevos() {
        return $this->huevos;
    }
}

Ahora podríamos hacer:

class Reptil extends Invertebrado {
 
    use Oviparo; // Usamos el trait para simular herencia múltiple
    private $escamas;
 
    public function getEscamas() {
        return $this->escamas;
    }
}

Si ahora creamos una nueva clase:

class Tortuga extends Reptil {
}

Herederá de Vertebrado, Reptil y Ovíparo.

A la creación de interfaz, clase abstracta y clases concretas es lo que se conoce como modelado en programación orientada a objetos.

La clase ReflectionClass

Devuelve información sobre una clase.

$reflection = new ReflectionClass("Tortuga");
Reflexion::export($reflexion); // Devuelve información sobre la clase
var_dump($reflexion->isAbstract()); // Es abstracta?
var_dump($reflexion->isInstantiable()); // Se puede instanciar?
var_dump($reflexion->isInternal()); // Es interna?

Constantes predefinidas

  • __FILE__
  • __LINE__
  • __CLASS__
  • __TRAIT__
  • __METHOD__
  • __NAMESPACE__
 

Funciones interesantes

  • get_declared_classes(): devuelve un array con el nombre de las clases definidas en nuestra instalación de PHP.
  • class_exists(): indica si la clase pasada por argumento está definida.
  • get_class_methods(): muestra los métodos de una clase.
  • method_exists(): indica si un método existe en una clase específica.
  • get_class(): indica la clase a la que pertenece la instancia.
  • is_a(): indica si una instancia pertenece a cierta clase.
  • get_parent_class(): devuelve la clase origen o padre de la clase solicitada.
  • is_subclass_of(): indica si las clases están en la misma jerarquía de clase.
informatica/programacion/programacion_orientada_a_objetos/php.1679048150.txt.gz · Última modificación: por tempwin