问题
How do I know what to load in a constructor and what to set using the set methods later on?
For example, I have a question class which most of the time will call the following vars:
protected $question;
protected $content;
protected $creator;
protected $date_added;
protected $id;
protected $category;
At the moment I have it so only the bare essentials $id, $question, and $content are set in the constructor so I don't start building up a huge list of constructor arguments. This however, means that when I make a new question object elsewhere, I have to set the other properties of that object straight after meaning 'setter code' getting duplicated all over the place.
Should I just pass them all into the constructor right away, do it the way I'm doing it already, or is there a better solution that I'm missing? Thanks.
回答1:
Depending on the language you can have multiple constructors for any one class.
回答2:
You could use an array as the parameter to the constructor or setter method.
Just example:
public function __construct($attributes = array()) {
$this->setAttributes($attributes);
}
public function setAttributes($attributes = array()) {
foreach ($attributes as $key => $value) {
$this->{$key} = $value;
}
}
回答3:
PHP doesn't support traditional constructor overloading (as other OO languages do). An option is to pass an array of arguments into the constructor:
public function __construct($params)
{
}
// calling it
$arr = array(
'question' => 'some question',
'content' => ' some content'
...
);
$q = new Question($arr);
Using that, you're free to pass a variable number of arguments and there is no dependency on the order of arguments. Also within the constructor, you can set defaults so if a variable is not present, use the default instead.
回答4:
I would pass an array to the constructor with the values I want to set.
public function __construct(array $values = null)
{
if (is_array($values)) {
$this->setValues($values);
}
}
Then you need a method setValues to dynamicly set the values.
public function setValues(array $values)
{
$methods = get_class_methods($this);
foreach ($values as $key => $value) {
$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
For this to work you need setter methods for your properties like setQuestion($value) etc.
回答5:
A fluent interface is another solution.
class Foo {
protected $question;
protected $content;
protected $creator;
...
public function setQuestion($value) {
$this->question = $value;
return $this;
}
public function setContent($value) {
$this->content = $value;
return $this;
}
public function setCreator($value) {
$this->creator = $value;
return $this;
}
...
}
$bar = new Foo();
$bar
->setQuestion('something')
->setContent('something else')
->setCreator('someone');
Or use inheritance...
class Foo {
protected $stuff;
public function __construct($stuff) {
$this->stuff = $stuff;
}
...
}
class bar extends Foo {
protected $moreStuff;
public function __construct($stuff, $moreStuff) {
parent::__construct($stuff);
$this->moreStuff = $moreStuff;
}
...
}
Or use optional parameters...
class Foo {
protected $stuff;
protected $moreStuff;
public function __construct($stuff, $moreStuff = null) {
$this->stuff = $stuff;
$this->moreStuff = $moreStuff;
}
...
}
In any case, there are many good solutions. Please dont use a single array as params or func_get_args or _get/_set/__call magic, unless you have a really good reason to do so, and have exhausted all other options.
来源:https://stackoverflow.com/questions/14937416/how-do-i-deal-with-multiple-contructor-arguments-or-class-variables