JTagua

Inicio » PHP » Clases y Objetos

Archivo de la categoría: Clases y Objetos

Tutorial PHP(53): Resolución de ámbito.

Tutorial PHP(52): Herencia de Objetos.

Tutorial PHP(51): Visibilidad.

Tutorial PHP(50): Constructores y Destructores.

Tutorial PHP(49): Autocarga de clases.

Autocarga de clases

Muchos desarrolladores que escriben aplicaciones orientadas a objetos crean un fichero fuente PHP para cada definición de clase. Una de las mayores molestias es tener que hacer una larga lista de includes al comienzo de cada script (uno por cada clase).

En PHP 5 esto ya no es necesario. Se puede definir una función __autoload() que es automáticamente invocada en caso de que se esté intentando utilizar una clase/interfaz que todavía no haya sido definida. Al invocar a esta función el motor de scripting da una última oportunidad para cargar la clase antes que PHP falle con un error.
Sugerencia

spl_autoload_register() proporciona una alternativa más flexible para la carga automática de clases. Por esta razón, el uso de __autoload() no se recomienda y puede quedar obsoleta o ser eliminada en el futuro.

Antes de 5.3.0, las excepciones lanzadas en la función __autoload no podían ser capturadas en el bloque catch y resultaba en un error fatal. Desde 5.3.0+ las excepciones lanzadas en la función __autoload pueden ser capturadas en el bloque catch, con una consideración. Si se lanza una excepción personalizada, la clase de dicha excepción debe estar disponible. La función __autoload puede usarse recursivamente para autocargar la clase de la excepción personalizada.

La autocarga no está disponible si se utiliza PHP en el modo interactivo CLI.

Si el nombre de la clase se utiliza, por ejemplo, en call_user_func(), puede contener algunos caracteres peligrosos tales como ../. Se recomienda no utilizar la entrada del usuario en tales funciones, o al menos verificar dicha entrada en __autoload().

Ejemplo #1 Ejemplo de autocarga

Este ejemplo intenta cargar las clases MiClase1 y MiClase2 desde los ficheros MiClase1.php y MiClase2.php respectivamente.

<?php
function __autoload($nombre_clase) {
    include $nombre_clase . '.php';
}

$obj  = new MiClase1();
$obj2 = new MiClase2();
?>

Ejemplo #2 Otro ejemplo de autocarga

Este ejemplo intenta cargar la interfaz ITest.

<?php
function __autoload($nombre) {
    var_dump($nombre);
}

class Foo implements ITest {
}

/*
string(5) "ITest"

Fatal error: Interface 'ITest' not found in ...
*/
?>

Ejemplo #3 Autocarga con manejo de excepciones para 5.3.0+

Este ejemplo lanza una excepción y demuestra los bloques try/catch.

<?php
function __autoload($nombre) {
    echo "Intentando cargar $nombre.\n";
    throw new Exception("Imposible cargar $nombre.");
}

try {
    $obj = new ClaseNoCargable();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

El resultado del ejemplo sería:

Intentando cargar ClaseNoCargable.
Imposible cargar ClaseNoCargable.

Ejemplo #4 Autocarga con manejo de excepciones para 5.3.0+ – Excepción personalizada ausente

Este ejemplo lanza una excepción para una excepción personalizada no cargable.

<?php
function __autoload($nombre) {
    echo "Intentando cargar $nombre.\n";
    throw new ExcepciónAusente("Imposible cargar $nombre.");
}

try {
    $obj = new ClaseNoCargable();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

El resultado del ejemplo sería:

Intentando cargar ClaseNoCargable.
Intentando cargar ExcepciónAusente.

Fatal error: Class ‘ExcepciónAusente’ not found in testExcepcionAusente.php on line 4

Ver también

unserialize()
unserialize_callback_func
spl_autoload()
spl_autoload_register()

Tutorial PHP(48): Constantes de clase.

Tutorial PHP(47): Propiedades de clase.

Propiedades de la clase.

Las variables pertenecientes a clases se llaman «propiedades». También se les puede llamar usando otros términos como «atributos» o «campos», pero para los propósitos de esta referencia se va a utilizar «propiedades». Éstas se definen usando una de las palabras clave public, protected, o private, seguido de una declaración normal de variable. Esta declaración puede incluir una inicialización, pero esta inicialización debe ser un valor constante, es decir, debe poder ser evaluada en tiempo de compilación y no debe depender de información en tiempo de ejecución para ser evaluada.

Véase Visibilidad para más información sobre el significado de public, protected, y private.

Con el fin de mantener la compatibilidad con PHP 4, PHP 5 continuará aceptando el uso de la palabra clave var en la declaración de propiedades en lugar de (o además de) public, protected, o private. Sin embargo, var ya no es necesaria. Entre las versiones 5.0 y 5.1.3 de PHP, el uso de var fue considerado obsoleto y emitía una advertencia de nivel E_STRICT, pero a partir de PHP 5.1.3 ya no está obsoleta y no emitirá la advertencia.

Si se declara una propiedad utilizando var en lugar de public, protected, o private, PHP tratará dicha propiedad como si hubiera sido definida como public.

Dentro de los métodos de una clase, las propiedades no estáticas pueden ser accedidas utilizando -> (el operador de objeto): $this->propiedad (donde propiedad es el nombre de la propiedad). Las propiedades estáticas pueden ser accedidas utilizando ::: self::$propiedad. Véase la palabra clave ‘static’ para más información sobre la diferencia entre propiedades estáticas y no estáticas.

La pseudo-variable $this está disponible dentro de cualquier método de clase cuando éste es invocado dentro del contexto de un objeto. $this es una referencia al objeto que se invoca (usualmente el objeto al que pertenece el método, pero posiblemente sea otro objeto, si el método es llamado estáticamente desde el contexto de un objeto secundario).

Ejemplo #1 Declaración de propiedades

<?php
class ClaseSencilla
{
   // Declaraciones de propiedades inválidas:
   public $var1 = 'hola ' . 'mundo';
   public $var2 = <<<EOD
hola mundo
EOD;
   public $var3 = 1+2;
   public $var4 = self::myStaticMethod();
   public $var5 = $myVar;

   // Declaraciones de propiedades válidas:
   public $var6 = myConstant;
   public $var7 = array(true, false);

   // Esto se permite sólo en PHP 5.3.0 y posteriores.
   public $var8 = <<<'EOD'
hola mundo
EOD;
}
?>

Nota: Existen varias funciones interesantes para manipular clases y objetos. Quizá pueda ser interesante echar un vistazo a las Funciones de clases/objetos.

A diferencia de heredocs, nowdocs puede ser utilizado en cualquier contexto de datos estáticos, incluyendo la declaración de propiedades.

Ejemplo #2 Ejemplo del uso de nowdoc para inicializar una propiedad

<?php
class foo {
   // A partir de PHP 5.3.0
   public $bar = <<<'EOT'
bar
EOT;
}
?>

Nota: El soporte para nowdoc fue agregado en PHP 5.3.0.

Tutorial PHP(46): Introducción a clases y objetos.

class

La definición básica de clases comienza con la palabra clave class, seguido por un nombre de clase, continuado por un par de llaves que encierran las definiciones de las propiedades y métodos pertenecientes a la clase.

El nombre de clase puede ser cualquier etiqueta válida que no sea una palabra reservada de PHP. Un nombre válido de clase comienza con una letra o un guión bajo, seguido de la cantidad de letras, números o guiones bajos que sea. Como una expresión regular, se expresaría de la siguiente forma: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.

Una clase puede tener sus propias constantes, variables (llamadas «propiedades»), y funciones (llamadas «métodos»).

Ejemplo #1 Definición simple de una clase

<?php
class SimpleClass
{
    // Declaración de la propiedad
    public $var = 'a default value';

    // Declaración del método
    public function displayVar() {
        echo $this->var;
    }
}
?>

La pseudo-variable $this está disponible cuando un método es invocado dentro del contexto de un objeto. $this es una referencia del objeto que invoca (usualmente el objeto al que el método pertenece, pero posiblemente sea otro objeto, si el método es llamado estáticamente desde el contexto de un objeto secundario).

Ejemplo #2 Algunos ejemplo de la pseudo-variable $this

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this está definida (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this no está definida.\n";
        }
    }
}

class B
{
    function bar()
    {
        // Nota: la siguiente línea arrojará un Warning si E_STRICT está habilitada.
        A::foo();
    }
}

$a = new A();
$a->foo();

// Nota: la siguiente línea arrojará un Warning si E_STRICT está habilitada.
A::foo();
$b = new B();
$b->bar();

// Nota: la siguiente línea arrojará un Warning si E_STRICT está habilitada.
B::bar();
?>

El resultado del ejemplo sería:

$this está definida (A)
$this no está definida.
$this está definida (B)
$this no está definida.

new

Para crear una instancia de una clase, la palabra clave new debe ser usada. Un objeto siempre se creará a menos que el objeto tenga un constructor que arroje una excepción en caso de error. Las clases deberían ser definidas antes de la instanciación (y en algunos casos esto es un requerimiento).

Si un string que contiene el nombre de una clase se usa con new, una nueva instancia de esa clase será creada. Si la clase está en un espacio de nombres, su nombre completo debe ser usado cuando se hace esto.

Ejemplo #3 Creación de una instancia

<?php
$instance = new SimpleClass();

// Esto también se puede hacer con variables:
$className = 'Foo';
$instance = new $className(); // Foo()
?>

En el contexto de una clase, es posible crear un nuevo objeto con new self y new parent.

Cuando se asigna una instancia de una clase ya creada a una nueva variable, ésta última accederá a la misma instancia como al objeto que le fue asignado. Esta conducta es la misma cuando se pasan instancias a una función. Una copia de un objeto ya creado se puede lograr a través de la clonación de la misma.

Ejemplo #4 Asignación de objetos

<?php

$instance = new SimpleClass();

$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned tendrá este valor';

$instance = null; // $instance y $reference se transforman en null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

El resultado del ejemplo sería:

NULL
NULL
object(SimpleClass)#1 (1) {
[«var»]=>
string(30) «$assigned tendrá este valor»
}

PHP 5.3.0 introdujo un par de nuevas maneras para crear instancias de un objeto:

Ejemplo #5 Creando nuevos objetos

<?php
class Test
{
    static public function getNew()
    {
        return new static;
    }
}

class Child extends Test
{}

$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);

$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);

$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>

El resultado del ejemplo sería:

bool(true)
bool(true)
bool(true)

extends

Una clase puede heredar los métodos y propiedades de otra clase al utilizar la palabra clave extends en la declaración de la clase. No es posible extender múltiples clases; una clase sólo puede heredar de una clase base.

Los métodos y propiedades heredados pueden ser sobrescritos con la redeclaración de éstos utilizando el mismo nombre que en la clase parent. Sin embargo, si la clase parent definió un método como final, éste no podrá ser sobrescrito. Es posible acceder a los métodos sobrescritos o propiedades estáticas referenciándolos con parent::.

Cuando se sobrescriben métodos, la cantidad y disposición de los parámetros debería ser la misma o PHP generará un error a nivel de E_STRICT. Esto no se aplica a los constructores, que permiten la sobrescritura con diferentes parámetros.

Ejemplo #6 Herencia simple de clases

<?php
class ExtendClass extends SimpleClass
{
    // Redefinición del método parent
    function displayVar()
    {
        echo "Clase extendida\n";
        parent::displayVar();
    }
}

$extended = new ExtendClass();
$extended->displayVar();
?>

El resultado del ejemplo sería:

Clase extendida
un valor por defecto

::class

Desde PHP 5.5, la palabra clave class también se usa para la resolución de nombres de clases. Se puede obtener un string con un nombre completamente cualificado de la clase NombreClase usando NombreClase::class. Esto es particularmete útil con clases con espacios de nombres.

Ejemplo #7 Resolución de nombres de clases

<?php
namespace NS {
    class NombreClase {
    }
    
    echo NombreClase::class;
}
?>

El resultado del ejemplo sería:

NS\NombreClase