concept-properties.md 4.72 KB
Newer Older
larnu committed
1 2 3
Propiedades
===========

4 5 6 7
En PHP, las variables miembro de clases también llamadas *propiedades*, son parte de la definición de la clase, y se
usan para representar el estado de una instancia de la clase (ej. para diferenciar una instancia de clase de otra).
A la práctica, a menudo, se puede querer gestionar la lectura o escritura de las propiedades de algunos momentos. Por
ejemplo, se puede querer eliminar los espacios en blanco (trim) de una cadena de texto cada vez que esta se asigne a
larnu committed
8 9 10 11 12 13
una propiedad de tipo `label`. Se *podría* usar el siguiente código para realizar esta tarea:

```php
$object->label = trim($label);
```

14 15 16 17
La desventaja del código anterior es que se tendría que ejecutar `trim()` en todas las partes del código que pudieran
establecer la propiedad `label`. Si en el futuro, la propiedad `label` tiene que seguir otro funcionamiento, como por
ejemplo que la primera letra tiene que estar en mayúsculas, se tendrán que modificar todas las secciones de código que
asignen el valor a la propiedad `label`. La repetición de código conlleva a bugs, y es una practica que se tiene que
larnu committed
18 19
evitar en la medida de lo posible.

20 21
Para solventar este problema, Yii introduce la clase base llamada [[yii\base\Object]] que da soporte a la definición
de propiedades basada en los métodos de clase *getter* y *setter*. Si una clase necesita más funcionalidad, debe
larnu committed
22 23
extender a la clase [[yii\base\Object]] o a alguna de sus hijas.

24 25
> Información: Casi todas las clases del núcleo (core) en el framework Yii extienden a [[yii\base\Object]] o a una de
  sus clases hijas. Esto significa que siempre que se encuentre un getter o un setter en una clase del núcleo, se
larnu committed
26 27
  puede utilizar como una propiedad.

28 29
Un método getter es un método cuyo nombre empieza por la palabra `get`: un metodo setter empieza por `set`. El nombre
añadido detrás del prefijo `get` o `set` define el nombre de la propiedad. Por ejemplo, un getter `getLabel()` y/o un
larnu committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
setter `setLabel()` definen la propiedad `label`, como se muestra a continuación:

```php
namespace app\components;

use yii\base\Object;

class Foo extends Object
{
    private $_label;

    public function getLabel()
    {
        return $this->_label;
    }

    public function setLabel($value)
    {
        $this->_label = trim($value);
    }
}
```

53
(Para ser claros, los métodos getter y setter crean la propiedad `label`, que en este caso hace una referencia interna
larnu committed
54 55
al nombre de atributo privado `_label`.)

56 57
Las propiedades definidas por los getter y los setters se pueden usar como variables de clase miembro. La principal
diferencia radica en que cuando esta propiedad se lea, se ejecutará su correspondiente método getter; cuando se asigne
larnu committed
58 59 60 61 62 63 64 65 66 67
un valor a la propiedad, se ejecutará el correspondiente método setter. Por ejemplo:

```php
// equivalente a $label = $object->getLabel();
$label = $object->label;

// equivalente a $object->setLabel('abc');
$object->label = 'abc';
```

68 69 70
Una propiedad definida por un getter sin un setter es de tipo *sólo lectura*. Si se intenta asignar un valor a esta
propiedad se producirá una excepción de tipo [[yii\base\InvalidCallException|InvalidCallException]]. Del mismo modo
que una propiedad definida con un setter pero sin getter será de tipo *sólo escritura*, cualquier intento de lectura
larnu committed
71 72 73 74
de esta propiedad producirá una excepción. No es común tener variables de tipo sólo escritura.

Hay varias reglas especiales y limitaciones en las propiedades definidas mediante getters y setters:

75
* Los nombres de estas propiedades son *case-insensitive*. Por ejemplo, `$object->label` y `$object->Label` son la
larnu committed
76
  misma. Esto se debe a que los nombres de los métodos en PHP son case-insensitive.
77 78
* Si el nombre de una propiedad de este tipo es igual al de una variable miembro de la clase, la segunda tendrá
  prioridad. Por ejemplo, si la anterior clase `Foo` tiene la variable miembro `label`, entonces la asignación
larnu committed
79
  `$object->label = 'abc'` afectará a la *variable miembro* 'label'; no se ejecutará el método setter `setLabel()`.
80
* Estas variables no soportan la visibilidad. No hay diferencia en definir los métodos getter o setter en una
larnu committed
81
  propiedad public, protected, o private.
82
* Las propiedades sólo se pueden definir por getters y setters *no estáticos*. Los métodos estáticos no se tratarán de
larnu committed
83 84
  la misma manera.

85 86
Volviendo de nuevo al problema descrito al principio de la guía, en lugar de ejecutar `trim()` cada vez que se asigne
un valor a `label`, ahora `trim()` sólo necesita ser invocado dentro del setter `setLabel()`. I si se tiene que añadir
larnu committed
87 88
un nuevo requerimiento, para que `label` empiece con una letra mayúscula, se puede modificar rápidamente el método `
setLabel()` sin tener que modificar más secciones de código. El cambio afectará a cada asignación de `label`.