Lo básico

class

La definición básica de una clase comienza con la palabra reservada class, seguida de un nombre de clase, y continuando con un par de llaves que encierran las definiciones de las propiedades y métodos pertenecientes a dicha clase.

El nombre de clase puede ser cualquier etiqueta válida, siempre 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 una cantidad arbitraria de letras, números o guiones bajos. Como 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 (llamados "métodos").

Ejemplo #1 Definición de una clase sencilla

<?php
class ClaseSencilla
{
    
// Declaración de una propiedad
    
public $var 'un valor predeterminado';

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

La pseudovariable $this está disponible cuando un método es invocado dentro del contexto de un objeto. $this es una referencia al objeto invocador (usualmente el objeto al cual el método pertenece, aunque puede que sea otro objeto si el método es llamado estáticamente desde el contexto de un objeto secundario). A partir de PHP 7.0.0, la llamada estática a un método no estático desde un contexto incompatible resulta en que $this no esté definido dentro del método. Una llamada estática a un método no estático desde un contexto no compatible está obsoleta desde PHP 5.6.0. A partir de PHP 7.0.0, una llamada estática a un método no estático está obsoleta en general (incluso si se llama desde un contexto compatible). Antes de PHP 5.6.0, tales llamadas ya ocasionaban un aviso de estrictez.

Ejemplo #2 Algunos ejemplos de la pseudovariable $this

Se asume que para este ejemplo error_reporting está inhabilitado; de lo contrario, el siguiente código emitirá avisos de estrictez y obsolescencia, respectivamente, dependiendo de la versión de PHP.

<?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()
    {
        
A::foo();
    }
}

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

A::foo();
$b = new B();
$b->bar();

B::bar();
?>

Salida del ejemplo anterior en PHP 5:

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

Salida del ejemplo anterior en PHP 7:

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

new

Para crear una instancia de una clase, se debe emplear la palabra reservada new. Un objeto se creará siempre 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 se emplea un string que contenga el nombre de una clase con new, se creará una nueva instancia de esa clase. Si la clase estuviera en un espacio de nombres, se debe utilizar su nombre completo al realizar esto.

Ejemplo #3 Creación de una instancia

<?php
$instancia 
= new ClaseSencilla();

// Esto también se puede hacer con una variable:
$nombreClase 'ClaseSencilla';
$instancia = new $nombreClase(); // new ClaseSencilla()
?>

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

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

Ejemplo #4 Asignación de objetos

<?php

$instancia 
= new ClaseSencilla();

$asignada   =  $instancia;
$referencia =& $instancia;

$instancia->var '$asignada tendrá este valor';

$instancia null// $instancia y $referencia son null

var_dump($instancia);
var_dump($referencia);
var_dump($asignada);
?>

El resultado del ejemplo sería:

NULL
NULL
object(ClaseSencilla)#1 (1) {
   ["var"]=>
     string(27) "$asignada tendrá este valor"
}

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

Ejemplo #5 Creación de nuevos objetos

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

class 
Hija extends Prueba
{}

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

$obj3 Prueba::getNew();
var_dump($obj3 instanceof Prueba);

$obj4 Hija::getNew();
var_dump($obj4 instanceof Hija);
?>

El resultado del ejemplo sería:

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

PHP 5.4.0 introdujo la posibilidad de acceder a un miembro de un objeto recién crecado en una única expresión:

Ejemplo #6 Acceder a un mimebro de un objeto recién creado

<?php
echo (new DateTime())->format('Y');
?>

El resultado del ejemplo sería algo similar a:

2016

Propiedades y métodos

Las propiedades y métodos de una clase viven en «espacios de nombres» diferentes, por tanto, es posible tener una propiedad y un método con el mismo nombre. Al hacer referencia tanto a una propiedad como a un método se utiliza la misma notación, y si se accederá a la propiedad o se llamará al método, solamente depende del contexto, es decir, si el empleo es el acceso a una variable o la llamada a una función.

Ejemplo #7 Acceso a propiedad contra llamada a método

class Foo
{
    public $bar = 'propiedad';
    
    public function bar() {
        return 'método';
    }
}

$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;

El resultado del ejemplo sería:

propiedad
método

Esto significa que llamar a una función anónima que ha sido asignada a una propiedad no es posible directamte. En su lugar, la propiedad ha de ser asignada primero a una variable, por ejemplo. A partir de PHP 7.0.0, es posible llamar a dicha propiedad directamente encerrándola entre paréntesis.

Ejemplo #8 Llamar a una función anónima almacenada en una propiedad

class Foo
{
    public $bar;
    
    public function __construct() {
        $this->bar = function() {
            return 42;
        };
    }
}

// A partir de PHP 5.3.0:
$obj = new Foo();
$func = $obj->bar;
echo $func(), PHP_EOL;

// Alternativamente, a partir de PHP 7.0.0:
echo ($obj->bar)(), PHP_EOL;

El resultado del ejemplo sería:

42

extends

Una clase puede heredar los métodos y propiedades de otra clase empleando la palabra reservada extends en la declaración de la clase. No es posible la extensión de 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 madre. Sin embargo, si la clase madre definió un método como final, éste no podrá ser sobrescrito. Es posible acceder a los métodos sobrescritos o a las propiedades estáticas haciendo referencia a ellos con parent::.

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

Ejemplo #9 Herencia de clases sencilla

<?php
class ClaseExtendida extends ClaseSencilla
{
    
// Redefinición del método padre
    
function mostrarVar()
    {
        echo 
"Clase extendida\n";
        
parent::mostrarVar();
    }
}

$extendida = new ClaseExtendida();
$extendida->mostrarVar();
?>

El resultado del ejemplo sería:

Clase extendida
un valor predeterminado

::class

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

Ejemplo #10 Resolución de nombres de clases

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

El resultado del ejemplo sería:

NS\NombreClase

Nota:

La resolución de nombres de clases con ::class es una transformación durante la compilación. Esto significa que, en el instante de crear el string del nombre de la clase, aún no se ha realizado ninguna autocarga. Como consecuencia, los nombres de clases se expanden incluso si la clase no existe. No se emite ningún error en tal caso.