PHP Setter / Getters和构造函数

时间:2012-07-31 12:33:32

标签: php constructor architecture setter getter

我一直在网上搜索这个,但我似乎找不到足够清晰的东西让我理解。我在Java上看到过类似的“类似”问题。

class animal{
    private $name;

    // traditional setters and getters
    public function setName($name){
        $this->name = $name;
    }

    public function getName(){
        return $this->name;
    }

    // animal constructors
    function __construct(){
       // some code here
    }

    // vs

    function __construct($name){
        $this->name = $name;
        echo $this->name;
    }
}

$dog = new animal();
$dog->setName("spot");
echo $dog->getName();

// vs

$dog = new animal("spot");
  1. 我应该通过setter和getter还是通过构造函数声明和访问我的私有字段?
  2. 哪一个是最佳做法?
  3. 我理解构造函数的目的(可能不是),但是如果我可以通过setter和getter声明和访问我的私有字段,那么构造函数有什么意义呢?
  4. 请注意......这是我第一次使用OOP进行Web开发和PHP,并且我试图通过编写一些代码让我的手“脏”来学习,以便我理解OOP中的某些东西。请保持简单。

6 个答案:

答案 0 :(得分:6)

这更像是语义问题,而不是每种说法的最佳实践。

在您的示例中,您的商业逻辑可能会确定动物总是需要一个名字。 因此,使用名称构造对象是有意义的。如果你不想允许 要改变动物的名字,那么你就不要写一个二传手。

class Animal 
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}

您可能拥有动物不必拥有的其他属性,例如拥有者 你只能写一个getter / setter,即。

class Animal
{
    private $name;
    private $owner;

    public function __construct($name)
    {    
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setOwner($owner)
    {
        $this->owner = $owner
    }
}

但是如果你发现你总是在同一时间与主人一起制造动物 为方便起见,您可能希望将其放在构造函数签名中

class Animal
{
    private $name;
    private $owner;

    public function __construct($name, $owner = null)
    {    
        $this->name = $name;
        $this->owner = $owner;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setOwner(Owner $owner)
    {
        $this->owner = $owner
    }

    public function getOwner()
    {
        return $this->owner;
    }
}

如果所有者是您的应用程序中的另一个类,则可以键入提示您的构造函数 需要特定类型(类)的所有者。所有这些都用于使您或其他开发人员更容易理解代码背后的一些要求/逻辑 - 以及可能在此处或那里捕获错误

class Owner 
{
    private $name;

    public function __construct($name)
    {    
        $this->name = $name;
    }
}

class Animal
{
    private $name;
    private $owner;

    public function __construct($name, Owner $owner = null)
    {    
        $this->name = $name;
        $this->owner = $owner;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setOwner(Owner $owner)
    {
        $this->owner = $owner
    }

    public function getOwner()
    {
        return $this->owner;
    }
}

// Create a new owner!
$dave = new Owner('Farmer Dave');

// a standard php empty object
$otherObj = new \stdClass();

// Create a new animal
$daisy = new Animal('Daisy');

// Farmer dave owns Daisy
$daisy->setOwner($dave);

// Throws an error, because this isn't an instance of Owner
$daisy->setOwner($otherObj);

// Set up Maude, with Dave as the owner, a bit less code than before!
$maude = new Animal('Maude', $dave);

答案 1 :(得分:2)

  1. 取决于。通常有人说:如果它是必需的依赖项,请使用构造函数,如果它是可选的,则使用getter / setter。
  2. 没有偏好或反对其中一个。
  3. 构造函数包含在创建对象后立即执行的代码,它应该使对象处于稳定且可用的状态。这是构造函数背后的想法,它在任何情况下都不起作用,但它应该给你一个想法,应该进入什么。
  4. 请注意,您甚至可以为同一属性实现构造函数参数和setter,例如,如果您希望稍后允许替换属性。

    $bingo = new Dog;
    echo $bingo->getName(); // DogHasNoNameException <-- maybe better as constructor argument?
    
    $bingo = new Dog('Bingo');
    echo $bingo->getName(); // "Bingo"
    $spike = new Dog; // Missing argument 
    
    $bingo->setName('Spike'); // Or maybe "rename()" ;)
    echo bingo->getName(); // "Spike"
    

答案 2 :(得分:2)

  

我应该通过setter来声明和访问我的私人字段   getters还是通过构造函数?哪一个是最好的做法?

两者。这取决于您的需求。如果在某些字段中需要值,则向其添加一个参数 __construct() - 执行此操作的方法。或者您也可以向__construct添加可选参数,以便为用户提供设置属性

的选项
  

我理解构造函数的目的(可能不是),但是什么是   如果我可以声明并访问我的私有,那么有一个构造函数   通过制定者和吸气者的领域?

构造函数应初始化需要初始化的属性。

答案 3 :(得分:2)

在我看来,写setter&amp;更为正确。 getter's,从那时起,物业的数量才会增长。然后__construct可以获取键名称的属性数组(property =&gt; value),并将它们设置为属性。

答案 4 :(得分:2)

  

我应该通过setter和getter还是通过构造函数声明和访问我的私有字段?

在这种情况下,我问自己:

  • 为什么我要创建一个方法来保持一行功能? (+构造)

  • 重构两个,三个,四个,五个或更多getter / setter与一个构造函数相比会有多痛苦?(+构造函数)

  • 记录两个,三个,四个,五个或更多getter / setter与一个构造函数相比有多难?(+构造函数)

  • 是否会有记录的默认值? (+构造函数)

  • 我喜欢文档并希望人们阅读吗? (+构造)

  • 初始值是否未定义?(+ Setter)

  • 是否存在一组等效形式(简写,国际,昵称),这些形式在所需参数的语法上是正确的? (+设置器)

  • 是否有一组带有默认值的可选参数? (+设置器)

  • 是否需要对字符串化和解析初始值? (+设置器)

  • 我不喜欢文档并期望人们进行实验吗? (+设置器)

  

哪一个是最佳做法?

Date对象似乎是大多数语言中最复杂的类,因此它的PHP实现将是最佳实践的良好参考。

  

如果我可以通过setter和getter声明和访问我的私有字段,那么拥有构造函数有什么意义呢?

在对象实例化时隐式调用构造函数,以封装其类型的结果数据结构的默认状态。

CDD: Context-Driven-Development Roles - Creator, Object, Behavior

<强>参考

答案 5 :(得分:1)

1&gt;你选择的是:如果需要依赖,那么好的练习使用构造函数,否则,使用getter。

2&gt;最好的做法是第一个,

实际上,你有一个名字,对于你的动物,但如果你添加一个类型和性别?并且你想分别调用type,sexe或name,第一种方法比第二种方法更好。

class animal{
private $name, $type, $sex;

// traditional setters and getters
public function setName($name){
    $this->name = $name;
}

public function setSex($sex){
    $this->sex = $sex;
}

public function setType($type){
    $this->type = $type;
}

public function getName(){
    return $this->name;
}

public function getSex(){
    return $this->sex;
}

public function getType(){
    return $this->type;
}

// animal constructors
function __construct(){
   // some code here
}

}

$dog = new animal();
$dog->setName("spot");
$dog->setSexe("male");
$dog->setType("dog");
echo $dog->getName().' is a '.$dog->getType().'('.dog->getSex().')';

3&gt;这取决于第一个问题... BUt Globaly我们总是需要一个依赖,样本:

class animal{
private $name, $type, $sex;

// traditional setters and getters
public function setName($name){
    $this->name = $name;
}

public function setSex($sex){
    $this->sex = $sex;
}

private function setType($type){
    // if type is string ( cat, dog, lion ) and you want
    // to linked string in an id in your database (1, 2, 3...). 
    // you want to call your database connection ( declared in you constructor) 
    // and search type id here. 
    $this->type = $type;
}

public function getName(){
    return $this->name;
}

public function getSex(){
    return $this->sex;
}

public function getType(){
    return $this->type;
}

// animal constructors
public function __construct($type){
    // for sample you want to open your database here
    this->setType($type);
}

public function __destruct(){
    // and you want to close your connection here.
}

}