2012-06-23 5 views
12

Мне нужно создать прибл. 5-7 классов, каждый класс будет содержать много членов (скажем, каждый класс будет содержать 20 членов). Я мог бы создать их с помощью открытого доступа, например:PHP OOP много сеттеров, геттеров

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

Мой предпочтительный способ, конечно, чтобы сделать эти члены приватным и создать получить/установить методы для каждого свойства. То есть

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

Но если у класса будет 20 свойств, у меня будет в добавок к этому добавить 40 методов. И моя забота здесь о том, как это замедлит сценарий и гораздо больше памяти, это потребует (помните, что у меня будет несколько классов, подобных этому).

Другим решением может быть использование магических функций __set, __get, но я не хочу, потому что завершение кода в разработке IDE не будет предлагать свойства, которые имеют решающее значение для меня.

Если бы это был скомпилированный язык (например, C++), у меня не было бы вопроса и он использовал бы решение с геттерами, сеттерами, но так как PHP интерпретируется языком, то я заинтересован в том, чтобы мои скрипты использовали меньше ОЗУ и были такими же как можно быстрее.

Заранее спасибо, любые мысли по этому вопросу были бы высоко оценены!


Мое мнение

Спасибо всем за ваши ответы, я просто хотел высказать свое мнение в случае, если кто-то будет искать ответ на этот вопрос.

Я не могу полностью согласиться с теми, кто говорит, что вам не следует заботиться о производительности, поскольку это задача оптимизаторов, я думаю, что это важный фактор (как бы это ни было для меня), когда мы имеем дело с интерпретируемым языком, таким как PHP мы всегда будем думать о памяти и скорости (все это напоминает мне время, когда я разрабатывал системные приложения для DOS, хех :), и вы всегда были ограничены плохим процессором и килобайтами от общей памяти, поэтому вы получили удовольствие, если вы мог бы сохранить дополнительный байт), в PHP-разработке у вас будет одинаковое изображение, независимо от того, сколько серверов вы добавите, количество пользователей будет всегда выше, так что вам всегда нужно решить, хотите ли вы следовать классическому/безопасному/правильному методу или чтобы избежать этого и получить некоторый выигрыш в скорости или памяти.

Итак, я считаю, что лучший способ здесь - использовать общедоступный доступ для всех участников и избегать геттеров/сеттеров для всех свойств и использовать закрытый доступ с методами get/set для свойств, требующих проверки или инициализации данных перед установкой значения.

Например:

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

Спасибо за тратить время на мой вопрос!

+14

это микро-оптимизация, и вы не должны беспокоиться об этом. –

+0

Ну, да, но перспектива добавить 280 методы (для 7 классов, 20 частных членов) только для этого немного пугает меня с точки зрения памяти/скорости. И, скажем, система растет, и я продлю эти классы на счет 15 .. тогда я получу 600 методов. с другой стороны, я понимаю, что эти методы get/set будут выполняться только при необходимости, но в то же время я предполагаю, что когда PHP будет анализировать исходный код, он будет строить таблицу методов в памяти, будет выполнять анализ синтаксиса, и все это может медленное замедление работы скрипта, правильно ли мое предположение? – user1476490

+1

Память относительно дешевая, а служебные данные метода - только для каждого класса (не для каждого экземпляра). PHP также выполняет трюки, такие как обработка нескольких запросов в одном и том же процессе (через mod_php и т. д.), поэтому начальное время загрузки (как ничтожно, как может быть) может быть полностью проигнорировано ... во всяком случае, * первым шагом * (в реальных условиях), чтобы увидеть, что такое «медленные» части системы. (FWIW, предположим, что существует 600 методов, и каждый метод «отходы» 1kb.Большой 600kb «потерян». На самом деле это не так много в схеме вещей ... особенно учитывая, насколько * каждая переменная * на PHP уже " отходы ";-) –

ответ

5

Простой тест показывает примеры принимают один и тот же объем памяти, не зависит от количества методов в классе:

Класс без методов:

class Test1 { } 

класса с 20 методами:

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

} 

Испытательная петля, одинаковая для обоих испытаний:

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

Результат для класса Test1 (без методов):

used: 3157408 

Результат для класса Test2 (20 методов):

used: 3157408 

Я запустить его в двух отдельных сценариев, так как работает два испытания в одном скрипте, по-видимому, было обнаружено некоторое внутреннее распределение PHP, а во втором тесте было меньше памяти, чем первое, независимо от того, кто из них первый или второй.

Несмотря на то, что вы действительно используете больше памяти для определения фактического класса, очевидно, эта стоимость возникает только один раз за класс, а не за экземпляр. Вам не нужно беспокоиться об использовании памяти.

+0

Я, к сожалению, не могу вставить много кода здесь, но вот что я сделал. Я создал test1.php с одним классом, а затем test2.php с классом и одним методом, а затем test3.php с классом, 20 частными свойствами, а затем 40 общедоступными методами get/set (со всеми возвращаемыми данными и т. Д.).). И выход Использовано памяти в конце концов, так вот что я получил: 'test1.php - 653,97 Kbytes' ' test2.php - 654,73 Kbytes' 'test3.php - 718,16 Kbytes' Это грубо, но в принципе, я полагаю, что каждый метод/переменная, не считая данные, которые она хранит, ест ~ 1кб. – user1476490

5

Но учитывая класс будет иметь 20 свойств

Имея это много свойств, как правило, является показателем неуместной информации. Проверьте, можете ли вы сгруппировать некоторые из них в собственные классы.

я буду иметь в дополнение к этому добавить 40 методов.

Совсем нет. Если эти классы не являются строгими структурами данных, вы не хотите, чтобы на них были Getters и Setters, потому что они разрушают инкапсуляцию. Поместите методы в открытый API, с помощью которых вы сообщаете объектам что-то делать.

И моя забота здесь как это будет медленно вниз сценарий и гораздо больше памяти для этого потребуется (помните, я буду иметь несколько классы, подобные этому).

Это не проблема.

Другим решением может быть использование магических функций __set, __get, но я не хочу, так как завершение кода в среде разработки не будет предлагать свойства, которые очень важно для меня ,

Современные IDE могут автозаполняться по магическим методам.

Однако, если вы уже обеспокоены производительности на микроуровне, то вы не хотите, магические методы, потому что те, безусловно, медленнее.

Кроме того, Магические методы не являются взаимозаменяемыми для получения и установки, но обработчики ошибок, которые получают сработавших когда называется недоступным свойство или метод.

Кроме того, магические методы неочевидные и сделать трудно читать API.

+0

Благодарим вас за подробный ответ. – user1476490

0

Примите во внимание, что мой код считается, что свойства имени были объявлены в нижнем регистре ...

<?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

Благодарим вас, но как будет работать над завершением кода, например, в eclipse или netbeans? – user1476490

0

Как было сказано выше, это довольно странно, что ваш класс должен иметь так много свойств. Однако иногда это может произойти (довольно редко). Но, как правило, эти свойства должны иметь некоторую ссылку: так что вы можете хранить их в хэш-карте, а не в качестве свойства. Затем вы просто подбираете один метод в качестве геттера.

Теперь это, безусловно, будет больше ресурсов, потребляющих, правда. Что касается автозавершения, использовать константы: вы просто ввести что-то вроде:

$my_class->getFromHashMap($parameter) 

И при вводе вашего параметра, вы будете использовать константу, как она хранится в классе: здесь, автозаполнение должно быть в состоянии помочь вы.

+0

Да, я в настоящее время сохраняю все свойства в ассоциативном массиве, но для конечного пользователя (разработчика) это не кристально понятно, как использовать их все, поэтому мне нужно использовать комментарии к завершению кода и комментарии к документу, плюс я хочу улучшить код путем проверки данных когда пользователь устанавливает переменную. Хэш-карта - хорошее решение, но это приведет к другим возможным проблемам (разработчик может ошибочно назвать имя параметра, я не смогу использовать рефакторинг, если я хочу переименовать параметр и т. Д.) – user1476490

+0

За исключением проверки данных, использование констант в качестве ключей для вашего хэш-файла должно решить большую часть проблемы, которую вы описываете (и вы даже можете предотвратить в своих сеттерах ключ, который не определен в ваших константах). – Raveline

0

Для того, чтобы свойства вашего класса, которые реализованы с помощью магических методов, которые будут highlited с помощью IDE просто использовать @property PHPDoc @property тег, как это:

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

} 

Подробнее о PHPDoc»@property здесь: http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html

Что касается других вопросов, поставленных под сомнение - комментарий Кары Хорвата полностью охватывает те PHP OOP a lot of setters, getters.

0

Вы можете попробовать это:

черта get_set {

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

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

}

Он будет работать на общественных и защищенных переменных. Вы можете добавить if (! Isset ($ this -> {$ what}) error()

Смежные вопросы