Какой лучший подход для инициализации свойств php?

Вот два способа инициализации переменных класса.

1-й метод

class Test {
    private $var1;
    private $var2;

    public function Test($var1,$var1) {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}
$objTest = new Test("value1","value2");

2-й метод

class Test {
    private $var1;
    private $var2;

    public function _set($var, $value) {
        $this->$$var = $value
    }
}
$objTest = new Test();
$objTest->_set('var1','value1');
$objTest->_set('var2','value2');

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


person Starx    schedule 16.03.2011    source источник
comment
Вы, кажется, не поняли концепцию конструкторов.   -  person BoltClock    schedule 16.03.2011
comment
@Мария, да вроде так. @BoltClock, я достаточно хорошо понимаю концепции конструкторов, но я прошу инициализацию переменных класса и методы для них.   -  person Starx    schedule 16.03.2011
comment
Кстати, терминология: в ООП переменная класса является static членом класса; у переменной класса есть только одно значение, общее для всех экземпляров этого класса. Вы показываете переменные экземпляра, которые в php называются properties< /я>.   -  person ToolmakerSteve    schedule 22.04.2019


Ответы (5)


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

Кроме того, смысл инкапсуляции в ООП заключается в том, что внутренняя работа класса непрозрачна для кода вне класса. Ваш второй метод нарушает эту инкапсуляцию и, следовательно, часть точки ООП, поскольку код вне класса должен знать о внутренней работе класса, например, об имени переменных. Что произойдет, если вы позже решите изменить имена переменных? Весь код ломается. Если бы к ним обращались через сеттеры/геттеры, старые функции можно было бы изменить, чтобы отразить изменения внутри класса, но код вне класса было бы трудно изменить. Кроме того, второй метод усложняет проверку значений.

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

class Test {
    private $var1;
    private $var2;

    public function Test($var1 = 'defaultValue', $var1 = 'defaultValue') {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}
$objTest = new Test();

В любом случае, если значения должны быть инициализированы кодом, то вы обязательно должны принудительно передать их в конструкторе. Если значения по умолчанию разрешены, то либо инициализируйте значения в конструкторе с отдельными сеттерами для переменных, либо просто значениями аргументов по умолчанию, как в приведенном примере. Однако не следует ожидать, что код установит критические значения с помощью сеттеров после вызова конструктора.

person Riimu    schedule 16.03.2011
comment
Пункт отмечен, но даже если я использую 1-й метод, я могу установить частные переменные, как мне нравится, на этот раз они ограничены только несколькими числами. И, используя второй метод, если я установлю какие-либо новые переменные, они будут общедоступными, а не частными. - person Starx; 16.03.2011
comment
Суть инкапсуляции в ООП заключается в том, что внутренняя работа класса непрозрачна для кода вне класса. Ваш второй метод нарушает эту инкапсуляцию и, следовательно, часть точки ООП, поскольку код вне класса должен знать о внутренней работе класса, например, об имени переменных. Что произойдет, если вы позже решите изменить имена переменных? Весь код ломается. Если к ним обращаются через сеттеры/геттеры, старые функции можно изменить, чтобы отразить изменения внутри класса, но код вне класса трудно изменить. Ваш второй метод также затрудняет проверку. - person Riimu; 16.03.2011
comment
действительно очень хороший момент. Я думаю, вы должны включить этот момент в свой ответ. - person Starx; 16.03.2011
comment
Добавил это к фактическому ответу. - person Riimu; 16.03.2011

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

person Ikke    schedule 16.03.2011
comment
Значит, неизбежные переменные класса лучше задавать с помощью конструкторов? - person Starx; 16.03.2011
comment
Да, для этого и нужен конструктор. Чтобы построить объект класса, чтобы иметь возможность делать это. - person Ikke; 16.03.2011

Интересно, почему вы определили свои переменные как частные? Закрытые члены существуют для самого класса, а не для использования через общедоступный интерфейс. Это может быть отслеживание некоторого значения, которое магический метод установки (__set) может изменить в любое время в программе, как во втором примере. Если вам нужно, чтобы ваши переменные были закрытыми (только для доступа к классу), используйте функцию-конструктор __construct($var1,$var2) или __construct($var1="defaultvalue",$var2=" defaultvalue"), поэтому в соответствии с вашим первым примером.

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

надеюсь, это поможет

person Cerian York    schedule 18.09.2011
comment
Я бы согласился с вами, за исключением случаев создания классов модели базы данных, где переменные-члены обычно защищены или закрыты и доступны через общедоступный интерфейс. Что, очевидно, является одним из многих случаев там. - person Starx; 18.09.2011

Что насчет этого

class A{

    public $x;
    public $y;
    function A($var1=10,$var2=15){   //the default value for the class
        $this->x=$var1;  
        $this->y=$var2;

    }
}

$object_of_A= new A(20,30);  //if you do not want to change the default value then
                               //pass no arguments
person Radheshyam Nayak    schedule 16.03.2011
comment
Нет, $x=$var1 не присваивает значение public $x. И когда вы его исправите, он будет похож на ответ @Rinuwise. - person Starx; 16.03.2011
comment
Этот код действителен. @Starx - вы неправильно понимаете, как свойства (здесь $x, $y) работают в классе. Вы думаете о проблеме со ссылкой на global $x в функции. Не то же самое. - person ToolmakerSteve; 22.04.2019
comment
@ToolmakerSteve, позже код был отредактирован и исправлен. :) - person Starx; 21.08.2019

Я думаю, что вы должны комбинировать оба метода.

Неизбежные свойства должны присутствовать в методе конструкции.

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

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

myConstructor($dsn)
myConstructor($dsn, $username, $password)
myConstructor($dsn, $username, $password, $port)
myConstructor($dsn, $username, $password, $port, $options)

Затем в «нижней» конструкции вы установите $options, затем вызовете «верхнюю» конструкцию, которая установит $port и вызовет «верхнюю» конструкцию... и т.д...

person j_freyre    schedule 16.03.2011
comment
FWIW, в то время как другие языки поддерживают множественную отправку, PHP не поддерживает. Однако он поддерживает значения по умолчанию для вызовов функций, что обычно работает довольно хорошо. (Этот вопрос помечен как PHP.) - person Charles; 16.03.2011
comment
@Starx - к сожалению, код, который он показывает, не разрешен в php - ошибка компиляции, как только появляется второй код с таким же именем. - person ToolmakerSteve; 22.04.2019