2012-06-23 15 views
12

Necesito crear aprox. 5-7 clases, cada clase contendrá muchos miembros (digamos que cada clase contendrá 20 miembros). Podría crearlas usando el acceso público, como:PHP OOP muchos setters, getters

class A { 
    public $myPropertyOne = ''; 
    public $myPropertyTwo = ''; 
    ... 
} 

Mi forma preferida, por supuesto, para hacer que estos miembros privada y crear GET/métodos set para cada propiedad. Es decir.

class A { 
    private $myPropertyOne = ''; 
    private $myPropertyTwo = ''; 

    public function getMyPropertyOne() { 
      return $this->myPropertyOne; 
    } 

    public function setMyPropertyOne($myPropertyOne) { 
      $this->myPropertyOne = $myPropertyOne; 
    } 

    public function getMyPropertyTwo() { 
      return $this->myPropertyTwo; 
    } 

    public function setMyPropertyTwo($myPropertyTwo) { 
      $this->myPropertyTwo = $myPropertyTwo; 
    } 
} 

Pero teniendo en cuenta que una clase tendrá 20 propiedades, tendré además de esto agregue 40 métodos. Y mi preocupación aquí es cómo esto ralentizará el guión y mucha más memoria que esto requerirá (recuerden que voy a tener varias clases como esta).

Otra solución podría ser usar funciones mágicas __set, __get pero no quiero, porque la finalización del código en el desarrollo IDE no sugerirá propiedades que son cruciales para mí.

Si esto fuera un lenguaje compilado (como C++) no tendría una pregunta y usaría la solución con getters, setters pero dado que PHP es lenguaje interpretado, estoy interesado en mis scripts para usar menos RAM y ser tan lo más rápido posible.

Gracias de antemano, cualquier idea con respecto a esta pregunta sería muy apreciada!


Mi opinión

Gracias a todos por sus respuestas, sólo quería compartir mi opinión, en caso de que alguien va a buscar una respuesta a esta pregunta.

No puedo estar totalmente de acuerdo con aquellos que dicen que no debería preocuparse por el rendimiento ya que esta es una tarea de optimizadores, creo que este es un factor importante (al menos para mí), cuando se trata de lenguaje interpretado como PHP siempre tendremos que pensar en la memoria y la velocidad (todo esto me recuerda el momento en que desarrollé aplicaciones de sistema para DOS, heh :) y siempre has estado limitado con poca CPU y kilobytes de RAM total, así que te alegrabas si podría guardar un byte adicional), en el desarrollo de PHP tiene la misma imagen, independientemente de cuántos servidores agregue, el recuento de los usuarios siempre será mayor, por lo que siempre debe decidir si desea seguir el método clásico/seguro/adecuado o para evitar esto y obtener algo de velocidad o memoria.

Así que ... mi opinión es que el mejor método es usar acceso público para todos los miembros y evitar getters/setters para todas las propiedades y usar acceso privado con métodos get/set para propiedades que requieren validación o inicialización de datos antes de que se establezca un valor.

Por ejemplo:

class B { 
    public $myPropertyOne = ''; 
    public $myPropertyTwo = ''; 
    private $myPropertyThree = array(); 


    public function getMyPropertyThree() { 
     return $this->myPropertyThree; 
    } 

    public function setMyPropertyThree($val) { 
     if(!is_array($val)) { 
      return; 
     } 

     $this->myPropertyThree = $val; 
    } 
} 

Gracias por dedicar tiempo a mi pregunta!

+14

esto es una micro-optimización, y usted nunca debe preocuparse por eso –

+0

Bueno, sí, pero una perspectiva para agregar 280 métodos (para 7 clases, 20 miembros privados) solo por esto un poco me asusta desde el punto de vista de la memoria/velocidad. Digamos que el sistema crece y extenderé esas clases hasta la cuenta de 15 ... entonces obtendré 600 métodos. Por otro lado, me doy cuenta de que estos métodos get/set se ejecutarán solo cuando sea necesario, pero al mismo tiempo asumo que cuando PHP analizará el código fuente, construirá una tabla de métodos en la memoria, realizará un análisis de sintaxis y todo esto puede ralentizar mucho el trabajo del script, ¿lo asumo? – user1476490

+1

La memoria es relativamente económica y la sobrecarga de métodos es solo por clase (no por instancia). PHP también hace trucos como manejar solicitudes múltiples en el mismo proceso (a través de mod_php, etc.) para que el tiempo de carga inicial (tan trivial como pueda ser) se pueda ignorar por completo ... en cualquier caso, * benchmark primero * (en condiciones reales) para ver cuáles son las partes "lentas" de un sistema. (FWIW, suponga que hay 600 métodos, y cada método "desperdicia" 1kb. Un enorme 600kb es "desperdiciado". No es mucho en el esquema de las cosas ... especialmente considerando cuánto * cada variable * en PHP ya tiene " desechos ";-) –

Respuesta

5

prueba simple muestra casos toman la misma cantidad de memoria, no afectado por el número de métodos en una clase:

Clase sin métodos:

class Test1 { } 

Clase con 20 métodos:

class Test2 { 

    function test1() { return true; } 
    function test2() { return true; } 
    function test3() { return true; } 
    function test4() { return true; } 
    function test5() { return true; } 
    function test6() { return true; } 
    function test7() { return true; } 
    function test8() { return true; } 
    function test9() { return true; } 
    function test10() { return true; } 
    function test11() { return true; } 
    function test12() { return true; } 
    function test13() { return true; } 
    function test14() { return true; } 
    function test15() { return true; } 
    function test16() { return true; } 
    function test17() { return true; } 
    function test18() { return true; } 
    function test19() { return true; } 
    function test20() { return true; } 

} 

Bucle de prueba, el mismo para ambas pruebas:

$test = array(); 
$base = memory_get_usage(); 
for ($i = 0; $i < 10000; $i++) { 
    $test[] = new ClassToBeTested(); 
} 
$used = memory_get_usage() - $base; 
print("used: $used\n"); 

Resultado para la clase Prueba1 (no hay métodos):

used: 3157408 

Resultado para la clase Prueba2 (20 métodos):

used: 3157408 

me he encontrado en dos guiones independientes, ya que correr las dos pruebas en una secuencia de comandos única aparentemente expuso parte de la asignación interna de PHP, y la segunda prueba consumió menos memoria que la primera, sin importar cuál es la primera o la segunda.

Si bien seguramente toma más memoria para la definición de clase real, aparentemente este costo se incurre solo una vez por clase, no por instancia. No tiene que preocuparse por el uso de la memoria.

+0

Desafortunadamente no puedo pegar mucho código aquí, pero esto es lo que hice. Creé test1.php con una sola clase, luego test2.php con una clase y un único método, y luego test3.php con clase, 20 propiedades privadas y luego 40 métodos públicos get/set (con todas las devoluciones, etc.) Y la memoria RAM en el extremo de salida total utilizado, por lo que aquí es lo que tengo: 'test1.php - 653,97 Kbytes' ' test2.php - 654,73 Kbytes' 'test3.php - 718,16 Kbytes' Esto es duro, pero Básicamente, supongo que cada método/variable sin contar los datos que contiene, come ~ 1kb. – user1476490

5

Pero teniendo en cuenta una clase tendrá 20 propiedades

Tener esta cantidad de propiedades suele ser un indicador de la información fuera de lugar. Comprueba si puedes agrupar algunos de ellos en Clases propias.

voy a tener, además de esto se añaden 40 métodos.

No, en absoluto. A menos que estas clases sean estructuras de datos tontas, no querrás Getters and Setters porque rompen la encapsulación. Ponga métodos en la API pública con la que le dice a los objetos que hagan cosas.

Y mi preocupación aquí es cómo esta desaceleración del guión y mucha más memoria para ello será necesario (recuerde que voy a tener varios clases como esta).

Esto no es un problema.

Otra solución podría ser el uso de funciones mágicas __set, __get pero yo no quiero, ya que la finalización de código en el IDE de desarrollo no sugieren propiedades que es crucial para mí .

IDEs modernos pueden autocompletar en métodos mágicos.

Sin embargo, si ya está preocupado por el rendimiento en el nivel micro, a continuación, usted no desea métodos mágicos porque esas son definitivamente más lento.

Aparte de eso, Métodos mágicos no son sustitutos de los captadores y definidores pero los controladores de error que se disparará cuando una propiedad inaccesibles o método fue llamado.

Además, los métodos mágicos son no evidente y crea para los discos para leer las API.

+0

Gracias por su respuesta detallada. – user1476490

0

Tome en cuenta que mi código considera que el nombre propiedades han sido declarados en minúsculas ...

<?php 

    class Modelo { 
     var $attr1 = "default"; 
     var $attr2 = 0; 


     public function __call($name, $arguments) 
     { 
      if (method_exists($this, ($method = $name))){ 
       return $this->$method(); 
      } 
      else{  
       $attribute = split("get",$name); 
       if(count($attribute)==2){ 
        $attribute = strtolower($attribute[1]); 
        if(isset($this->$attribute)){ 
         return ($this->$attribute); 
        } 
       }else{ 
        $attribute = split("set",$name); 
        if(count($attribute)==2){ 
         $attribute = strtolower($attribute[1]); 
         if(isset($this->$attribute) && count($arguments)==1){ 
          $this->$attribute=$arguments[0]; 
         }else{ 
          die("$name number of arguments error: ".join($arguments,",")); 
         } 
        }else{ 
         die("$name doesn't exist!"); 
        }    
       }   
      } 
     } 


    } 

    echo "<pre>"; 
    $m = new Modelo(); 
    print_r(
     array(
      "objetct"=>$m 
      ,"getAttr1"=>$m->getAttr1() 
      ,"getAttr2"=>$m->getAttr2() 
     ) 
    ); 
    echo "setAttr1\n"; 
    $m->setAttr1("by set method"); 
    print_r(
     array(
      "objetct"=>$m 
      ,"getAttr1"=>$m->getAttr1() 
      ,"getAttr2"=>$m->getAttr2() 
     ) 
    ); 

    ?> 
+0

Gracias, pero ¿cómo funcionará el código de finalización en eclipse o netbeans en este caso? – user1476490

0

Como se ha dicho antes, es bastante extraño que su clase debe tener tantas propiedades. Sin embargo, a veces (aunque rara vez) suceden. Pero normalmente, esas propiedades deberían tener una especie de vínculo: para que pueda almacenarlas en un hashmap y no en una propiedad. Entonces solo necesitas un método como getter.

Ahora, seguramente consumirá más recursos, es cierto. En cuanto a la terminación automática, utilizar constantes: usted acaba de escribir algo como:

$my_class->getFromHashMap($parameter) 

Y al escribir el parámetro, va a utilizar la constante como se encuentra almacenada en la clase: aquí, el autocompletar debería ser capaz de ayudar tú.

+0

Sí, actualmente mantengo todas las propiedades en una matriz asociativa, pero esto no es claro para el usuario final (desarrollador) cómo usarlas todas, así que tengo que usar la finalización de código y comentarios de doc. Además, quiero mejorar el código validando datos cuando el usuario establece variable. El mapa Hash es una buena solución, pero esto dará lugar a otros posibles problemas (un desarrollador puede escribir mal el nombre del parámetro, no podré usar la refactorización si deseo cambiar el nombre de un parámetro, etc.) – user1476490

+0

Excepto por la validación de datos, el uso de constantes como claves para su hashmap debería resolver la mayor parte del problema que está describiendo (e incluso puede evitar, en sus instaladores, usar una clave que no esté definida en sus constantes). – Raveline

0

Haciendo propiedades de su clase que implementan mediante métodos mágicos para ser highlited por el IDE sólo tiene que utilizar @property PHPDoc @property etiqueta, como este:

<?php 
/** 
* @property int id Blog post ID 
* @property string title Blog post Title 
*/ 
class Post { 

} 

Más sobre PHPDoc' @property aquí: http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html

En cuanto a otros asuntos cuestionados, el comentario de Karoly Horvath cubre completamente esos PHP OOP a lot of setters, getters.

0

Usted podría intentar esto:

rasgo get_set {

public function set($what, $value) 
{ 
    $this->{$what} = $value; 
} 

public function get($what) 
{ 
    return $this->{$what}; 
} 

}

Se trabajará sobre las variables públicas y protegidas. Puede agregar if (! Isset ($ this -> {$ what}) error()