简体   繁体   English

PHP 设置器/获取器和构造器

[英]PHP Setters/Getters and Constructor

I have been searching for this online, but I can't seem to find something that is clear enough for me to understand.我一直在网上搜索这个,但我似乎找不到足够清晰的东西让我理解。 I have seen "similiar" questions on here about this in Java.我在 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. Should I declare and access my private fields through setters and getters or through the constructor?我应该通过 setter 和 getter 还是通过构造函数声明和访问我的私有字段?
  2. Which one is the best practice?哪一个是最佳实践?
  3. I understand the purpose of a constructor(maybe not), but what is the point of having a constructor if I can declare and access my private fields through setters and getters?我了解构造函数的目的(也许不是),但是如果我可以通过 setter 和 getter 声明和访问我的私有字段,那么拥有构造函数的意义何在?

Please note...this is my first time using OOP with web development and PHP, and I'm trying to learn by getting my hands "dirty" by writing some code in order for me to understand certain things in OOP. Please note...this is my first time using OOP with web development and PHP, and I'm trying to learn by getting my hands "dirty" by writing some code in order for me to understand certain things in OOP. Please keep it simple.请保持简单。

It is more a matter of semantics than best practice per say. 这更像是语义问题,而不是每种说法的最佳实践。

In your example, your buisness logic may determine that an animal always needs a name. 在您的示例中,您的商务逻辑可能会确定动物总是需要一个名字。 So it makes sense to construct the object with a name. 因此,使用名称构造对象是有意义的。 If you do not want to allow an animal's name to be changed, then you don't write a setter. 如果您不想允许更改动物的名字,那么您不会写一个二传手。

ie

class Animal 
{
    private $name;

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

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

You may have other properties that an animal doesn't have to have, like an owner that you only write a getter/setter for ie 您可能拥有动物不必拥有的其他属性,例如您只为其编写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
    }
}

But if you find that you are always creating an animal with an owner at the same time you may want to put that in the contructor signature for convenience 但是如果你发现你总是在同时拥有一个拥有者的动物你可能想把它放在构造函数签名中以方便

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

If the owner is another class in your application, you can type hint that your constructor needs an owner of a specific type (class). 如果所有者是应用程序中的另一个类,则可以键入提示,表明构造函数需要特定类型(类)的所有者。 All of this is used to make it easier for you, or another developer to understand some of the requirements/logic behind your code - as well as potentially catching a bug here or there 所有这些都用于使您或其他开发人员更容易理解代码背后的一些要求/逻辑 - 以及可能在此处或那里捕获错误

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

Should I declare and access my private fields through setters and getters or through the constructor? 我应该通过setter和getter还是通过构造函数声明和访问我的私有字段?

In situations like this, I ask myself: 在这种情况下,我问自己:

  • Why should I create a method just to hold a one line function? 为什么我要创建一个方法来保持一行功能? (+Constructor) (+构造)

  • How painful is it going to be to refactor two, three, four, five or more getters/setters vs one constructor?(+Constructor) 重构两个,三个,四个,五个或更多getter / setter与一个构造函数相比会有多痛苦?(+构造函数)

  • How hard is it going to be to document two, three, four, five or more getters/setters vs one constructor?(+Constructor) 记录两个,三个,四个,五个或更多getter / setter与一个构造函数相比有多难?(+构造函数)

  • Is there going to be a default value which will be documented? 是否会有记录的默认值? (+Constructor) (+构造)

  • Do I like documentation and expect people to read? 我喜欢文档并希望人们阅读吗? (+Constructor) (+构造)

  • Will the initial value be undefined?(+Setter) 初始值是否未定义?(+ Setter)

  • Is there a set of equivalent forms (shorthand, international, nicknames) which will all be acceptable as syntatically correct for required arguments? 是否存在一组等效形式(简写,国际,昵称),这些形式都可以被接受为所需参数的语法正确? (+Setter) (+设置器)

  • Is there a set of optional arguments with default values? 是否有一组带有默认值的可选参数? (+Setter) (+设置器)

  • Is there a common need to stringify and parse the initial value? 是否需要对字符串化和解析初始值? (+Setter) (+设置器)

  • Do I dislike documentation and expect people to experiment? 我不喜欢文档并期望人们进行实验吗? (+Setter) (+设置器)

Which one is the best practice? 哪一个是最佳做法?

The Date object seems to be the most complex class in most languages, so its PHP implementation would be a good reference for best practices. Date对象似乎是大多数语言中最复杂的类,因此它的PHP实现将是最佳实践的一个很好的参考。

What is the point of having a constructor if I can declare and access my private fields through setters and getters? 如果我可以通过setter和getter声明和访问我的私有字段,那么拥有构造函数有什么意义呢?

A constructor is implicitly invoked upon object instantiation in order to encapsulate the default state of the resulting data structure of its type. 在对象实例化时隐式调用构造函数,以封装其类型的结果数据结构的默认状态。

CDD:上下文驱动的开发角色 - 创建者,对象,行为

References 参考

  1. Depends. 要看。 Usually one say: If it's a required dependency, use the constructor, if it's optional, use getter/setter. 通常有人说:如果它是必需的依赖项,请使用构造函数,如果它是可选的,则使用getter / setter。
  2. There is no preference for, or against one of them. 对他们中的一个没有偏好或反对。
  3. The constructor contains code, that is executed right after the object is created and it should leave the object in a stable and useable state. 构造函数包含在创建对象后立即执行的代码,它应该使对象处于稳定且可用的状态。 Thats the idea behind the constructor and it doesn't work in any case, but it should give you an idea, what should go into it. 这是构造函数背后的想法,它在任何情况下都不起作用,但它应该给你一个想法,应该进入什么。

Note, that you can even implement both constructor arguments and setters for the same property, for example if you want to allow to replace property later. 请注意,您甚至可以为同一属性实现构造函数参数和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"

Should I declare and access my private fields through setters and getters or through the constructor? 我应该通过setter和getter还是通过构造函数声明和访问我的私有字段? Which one is the best practice? 哪一个是最佳做法?

Both. 都。 It depends on your needs. 这取决于您的需求。 If need a value in certain fields you add a param to the __construct() -Method to do so. 如果在某些字段中需要值,则向__construct() Method添加一个参数来执行此操作。 Or you can also add an optional Param to __construct to give the user the option to set the attribute 或者您也可以向__construct添加可选的Param,以便为用户提供设置属性的选项

I understand the purpose of a constructor(maybe not), but what is the point of having a constructor if I can declare and access my private fields through setters and getters? 我理解构造函数的目的(可能不是),但如果我可以通过setter和getter声明和访问我的私有字段,那么拥有构造函数有什么意义呢?

The contructor should initialize your attributes which need to be initialized. 构造函数应该初始化需要初始化的属性。

In my opinion, it is more correct to write setter's & getter's, since then, the number of properties will only grow. 在我看来,编写setter和getter更为正确,从那以后,属性的数量才会增长。 And the __construct can then take an array of properties of the names of the keys (property => value), and set them to properties. 然后__construct可以获取键名称的属性数组(property => value),并将它们设置为属性。

1 > That's your chose : if dependency is required, good practise use the constructor, else, use getter. 1>这是你的选择:如果需要依赖,好的做法使用构造函数,否则,使用getter。

2 > for the best practise is the first, 2>最佳实践是第一个,

Actually, you have a name, for your animal, but if you add a type and sex? 实际上,你有一个名字,对于你的动物,但如果你添加一个类型和性别? and you want to call type, sexe or name separatly, first method is more better than the second. 并且你想分别调用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 > that depends first question... BUt Globaly we are always one dependency required, for sample: 3>这取决于第一个问题... 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.
}

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM