lunes, 19 de enero de 2015

Propiedades

En PHP, las variables miembro de clase también se denominan propiedades. Estas variables son parte de la definición de la clase, y se utilizan para representar el estado de una instancia de clase (es decir, para diferenciar una instancia de la clase de otra). En la práctica, es posible que a menudo se requiera manejar la lectura o escritura de las propiedades en forma especial. Por ejemplo, es posible que necesitemos recortar una cadena cuando está siendo asignado a una propiedad label (etiqueta). Podríamos utilizar el siguiente código para dicho objetivo:

$object->label trim($label);

El inconveniente del código anterior es que tendríamos que llamar a trim() en todas partes del código en el que necesitemos la propiedad label. Si, en el futuro, la propiedad label tiene un nuevo requisito, como que la primera letra debe ser mayúscula, deberemos tener que volver a modificar en cada parte de nuestro código donde se utiliza la propiedad label. El repetir código nos lleva a los bugs (en unas partes actualizamos y en otras no), y es una práctica que debemos evitar en la medida de lo posible.

Para solventar este problema, Yii introduce una clase base llamada yii\base\Object que soporta la definición de propiedades basado en los métodos getter y setter. Si una clase necesita esa funcionalidad, debe extenderse desde yii\base\Object, o desde una clase hija.

Información: Casi todas las clases del núcleo de Yii se extienden de yii\base\Object o una clase hija. Esto significa que cada vez que veamos un getter o setter en una clase principal, se puede utilizar como una propiedad.

Un método de obtención es un método cuyo nombre comienza con la palabra get; un método para establecer un valor comienza con set. El nombre después de el prefijo get o set define el nombre de una propiedad. Por ejemplo, un obtenedor getLabel() y/o un establecedor setLabel() define una propiedad denominada label, como se muestra en el siguiente código:

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);
    }
}

Para estar claros, en este caso, los métodos get y set crean la propiedad label, que en este caso se refiere internamente a un atributo privado llamado _label.

Propiedades definidas por los captadores (get) y definidores (set) se pueden utilizar como variables miembro de clase. La principal diferencia es que cuando esas propiedades se está leyendo, se llama al método getter correspondiente; cuando la propiedad se le asigna un valor, se llama al método setter correspondiente. Por ejemplo:

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

Una propiedad definida por un captador (get) sin un definidor (set) es de sólo lectura. Tratar de asignar un valor a una propiedad causará un InvalidCallException. De manera similar, una propiedad definida por un definidor (set) sin un captador (get) es solamente de escritura, y tratar de leer este tipo de propiedad también provocará una excepción. No es común tener propiedades de sólo escritura.

Hay varias reglas especiales y limitaciones para las propiedades definidas a través de captadores (get) y definidores (set):

  • Los nombres de esas propiedades no son sensibles a mayúsculas. Por ejemplo, $object->label y $object->Label son los mismos. Esto se debe a que los nombres de métodos en PHP no son sensibles a mayúsculas.
  • Si el nombre de una propiedad de este tipo es el mismo que una variable miembro de la clase, este último tendrá prioridad. Por ejemplo, si lo clase Foo tiene una variable miembro label, entonces, la asignación de $object->label = 'abc' afectará a la variable miembro 'label'; esa línea no llamaría al método setLabel().
  • Estas propiedades no son compatibles con la visibilidad. No hace ninguna diferencia con el método captador (get) o definidor (set) especificar si la propiedad es pública, protegida o privada.
  • Las propiedades sólo pueden ser definidas por los captadores y / o emisores no estáticos. Los métodos estáticos no serán tratados de la misma manera.

Volviendo de nuevo al problema descrito al inicio de esta entrada, en lugar de llamar trim() en todas partes de un label donde se le asigna valor, ahora sólo necesitamos invocar a trim() en el definidor setLabel(). Y si un nuevo requisito hace necesario que la etiqueta inicie con mayúscula, el método setLabel() lo podemos modificar rápidamente para adecuarlo a los nuevos requisitos sin tener que tocar el resto de nuestro código. El cambio afectará universalmente a cada asignación de label.


También te puede interesar:
Configuraciones
Comportamientos (Behaviors)
Eventos
Componentes

No hay comentarios.:

Publicar un comentario

Nota: sólo los miembros de este blog pueden publicar comentarios.