visual studio setters getters generate code and php oop

studio - ¿Es esta una forma razonable de manejar getters/setters en una clase de PHP?



php getter setter generator (8)

Voy a intentar algo con el formato de esta pregunta y estoy muy abierto a sugerencias sobre una mejor manera de manejarlo.

No quería arrojar un montón de código en la pregunta, así que publiqué el código para la clase en refactormycode.

clase base para un fácil manejo de la propiedad de la clase

Mi idea era que la gente puede publicar fragmentos de código aquí o hacer cambios en refactormycode y publicar enlaces a sus refactorizaciones. Formularé votaciones y aceptaré una respuesta (suponiendo que haya un "ganador" claro) en función de eso.

En cualquier caso, en la clase en sí:

Veo mucho debate sobre los métodos get / setter class y es mejor simplemente acceder directamente a las variables de propiedades simples o si cada clase tiene explícitos los métodos get / set definidos, bla, bla, bla. Me gusta la idea de tener métodos explícitos en caso de que tenga que agregar más lógica más adelante. Entonces no tienes que modificar ningún código que use la clase. Sin embargo, odio tener un millón de funciones que se ven así:

public function getFirstName() { return $this->firstName; } public function setFirstName($firstName) { return $this->firstName; }

Ahora estoy seguro de que no soy la primera persona en hacer esto (espero que haya una forma mejor de hacerlo que alguien pueda sugerir).

Básicamente, la clase PropertyHandler tiene un __call método mágico. Todos los métodos que vienen a través de __call que comienzan con "get" o "set" se enrutan a funciones que establecen o recuperan valores en una matriz asociativa. La clave en la matriz es el nombre del método de llamada después de obtener o establecer. Por lo tanto, si el método que entra en __call es "getFirstName", la clave del arreglo es "FirstName".

Me gustó usar __call porque automáticamente se ocupará del caso donde la subclase ya tiene definido un método "getFirstName". Mi impresión (y puedo estar equivocado) es que los métodos mágicos __get & __set no hacen eso.

Así que aquí hay un ejemplo de cómo funcionaría:

class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } } $props = new PropTest(); $props->setFirstName("Mark"); echo $props->getFirstName();

Tenga en cuenta que PropTest en realidad no tiene los métodos "setFirstName" o "getFirstName" y tampoco lo hace PropertyHandler. Todo lo que hace es manipular valores de matriz.

El otro caso sería donde su subclase ya está extendiendo algo más. Como no puede tener una herencia múltiple verdadera en PHP, puede hacer que su subclase tenga una instancia de PropertyHandler como una variable privada. Tienes que agregar una función más, pero luego las cosas se comportan exactamente de la misma manera.

class PropTest2 { private $props; public function __construct() { $this->props = new PropertyHandler(); } public function __call($method, $arguments) { return $this->props->__call($method, $arguments); } } $props2 = new PropTest2(); $props2->setFirstName(''Mark''); echo $props2->getFirstName();

Observe cómo la subclase tiene un método __call que simplemente pasa todo junto al método PropertyHandler __call.

Otro buen argumento en contra de manejar getters y setters de esta manera es que hace que sea realmente difícil documentar.

De hecho, es básicamente imposible utilizar cualquier tipo de herramienta de generación de documentos, ya que los métodos explícitos que se deben documentar no existen.

Por el momento, he abandonado este enfoque. Fue un ejercicio de aprendizaje interesante, pero creo que sacrifica demasiada claridad.


@Marca

Pero incluso su método requiere una nueva declaración del método, y de alguna manera le quita la ventaja de ponerlo en un método para que pueda agregar más lógica, porque para agregar más lógica se requiere la declaración anticuada del método, de todos modos. En su estado predeterminado (que es donde es impresionante en lo que detecta / hace), su técnica no ofrece ninguna ventaja (en PHP) sobre los campos públicos. Está restringiendo el acceso al campo pero dando carta blanca a través de métodos de acceso que no tienen ninguna restricción propia. No estoy al tanto de que los accesos explícitos sin marcar ofrecen ninguna ventaja sobre los campos públicos en cualquier idioma, pero las personas pueden y deben sentirse libres de corregirme si me equivoco.


Me gusta tener métodos en lugar de simplemente usar campos públicos, pero mi problema con la implementación predeterminada de PHP (usando __get () y __set ()) o su implementación personalizada es que no está estableciendo getters y setters en una propiedad base. Mi problema con esto es que agregar "más lógica más tarde" requiere que agregue lógica general que se aplica a todas las propiedades a las que se accede con el captador / definidor o que usa if o cambia las declaraciones para evaluar a qué propiedad está accediendo para que pueda aplicar lógica específica.

Me gusta su solución, y lo aplaudo por ello, simplemente no estoy satisfecho con las limitaciones que PHP tiene cuando se trata de métodos de acceso implícitos.


Sí, es correcto, las variables deben declararse manualmente, pero lo encuentro mejor porque temo un error tipográfico en el colocador

$props2->setFristName(''Mark'');

generará automáticamente una nueva propiedad (FristName en lugar de FirstName) lo que dificultará la depuración.


Siempre he manejado este problema de manera similar con un __call que termina casi como código de placa de caldera en muchas de mis clases. Sin embargo, es compacto y utiliza las clases de reflexión para agregar solo getters / setters a las propiedades que ya ha establecido (no agregará nuevas). Simplemente agregando el getter / setter explícitamente agregará funcionalidad más compleja. Espera ser

El código se ve así:

/** * Handles default set and get calls */ public function __call($method, $params) { //did you call get or set if ( preg_match( "|^[gs]et([A-Z][/w]+)|", $method, $matches ) ) { //which var? $var = strtolower($matches[1]); $r = new ReflectionClass($this); $properties = $r->getdefaultProperties(); //if it exists if ( array_key_exists($var,$properties) ) { //set if ( ''s'' == $method[0] ) { $this->$var = $params[0]; } //get elseif ( ''g'' == $method[0] ) { return $this->$var; } } } }

Agregando esto a una clase donde ha declarado propiedades predeterminadas como:

class MyClass { public $myvar = null; } $test = new MyClass; $test->setMyvar = "arapaho"; echo $test->getMyvar; //echos arapaho

La clase de reflexión puede agregar algo útil a lo que propones. Buena solución @Mark.


Recientemente, también pensé en manejar getters y setters de la manera que sugeriste (el segundo enfoque fue mi favorito, es decir, el conjunto $ props privado), pero lo descarté porque no habría funcionado en mi aplicación.

Estoy trabajando en una aplicación bastante grande basada en SoapServer y la interfaz soap de PHP 5 inyecta los valores que se transmiten vía soap directamente en la clase asociada, sin preocuparse por las propiedades existentes o no existentes en la clase.


No puedo evitar poner mis 2 centavos ...

He __get a usar __get y __set en esta manor http://gist.github.com/351387 (similar a la forma en que lo hace la doctrina), y luego solo accediendo a las propiedades a través de $obj->var en un exterior de la clase. De esta forma, puede anular la funcionalidad según sea necesario en lugar de hacer una gran función __get o __set , o anular __get y __set en las clases secundarias.


La forma en que lo hago es la siguiente:

class test { protected $x=''''; protected $y=''''; function set_y ($y) { print "specific function set_y/n"; $this->y = $y; } function __call($function , $args) { print "generic function $function/n"; list ($name , $var ) = split (''_'' , $function ); if ($name == ''get'' && isset($this->$var)) { return $this->$var; } if ($name == ''set'' && isset($this->$var)) { $this->$var= $args[0]; return; } trigger_error ("Fatal error: Call to undefined method test::$function()"); } } $p = new test(); $p->set_x(20); $p->set_y(30); print $p->get_x(); print $p->get_y(); $p->set_z(40);

Cuál será la salida (se agregarán saltos de línea para mayor claridad)

generic function set_x specific function set_y generic function get_x 20 generic function get_y 30 generic function set_z Notice: Fatal error: Call to undefined method set_z() in [...] on line 16


@Brian

Mi problema con esto es que agregar "más lógica más tarde" requiere que agregue lógica general que se aplica a todas las propiedades a las que se accede con el captador / definidor o que usa if o cambia las declaraciones para evaluar a qué propiedad está accediendo para que pueda aplicar lógica específica.

Eso no es del todo cierto. Toma mi primer ejemplo:

class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } } $props = new PropTest(); $props->setFirstName("Mark"); echo $props->getFirstName();

Digamos que necesito agregar algo de lógica para validar FirstNames. Todo lo que tengo que hacer es agregar un método setFirstName a mi subclase y ese método se usa automáticamente en su lugar.

class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } public function setFirstName($name) { if($name == ''Mark'') { echo "I love you, Mark!"; } } }

Simplemente no estoy satisfecho con las limitaciones que PHP tiene cuando se trata de métodos de acceso implícitos.

Concuerdo completamente. Me gusta la forma en que Python maneja esto (mi implementación es solo una tosca estafa).