Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php OOP-使用私有属性和公共getter_Php_Oop - Fatal编程技术网

Php OOP-使用私有属性和公共getter

Php OOP-使用私有属性和公共getter,php,oop,Php,Oop,只是一个简单的问题。我见过许多这样实现代码的案例: class User { private $id; private $firstname; private $lastname; public function __construct() { some code } public function getId() { return $this->id; } public function getFirstname() { return

只是一个简单的问题。我见过许多这样实现代码的案例:

class User
{
    private $id;
    private $firstname;
    private $lastname;

    public function __construct() { some code }

    public function getId() { return $this->id; }

    public function getFirstname() { return $this->firstname; }

    public function setFirstname($value) { $this->firstname = $value; }
}

// And properties are accessed like:
$user->getFirstname();
$user->getId();
class User
{
    private $firstname = 'abc';
    private $lastname  = 'def';

    public function getName()
    {
        return $this->firstname . ' ' . $this->lastname;
    }
}
那么,使用私有属性并使用公共getter而不是将属性公开并直接访问它们的原因是什么呢

$user->firstname;
附言:如果我用第二种方法可以吗

编辑

似乎我在问这个问题之前没有好好研究过(我猜我用了错误的键来搜索这个主题)。以下是(几乎)相同问题的另一个好答案:

基本上,在我的例子中,使用getter和setter的一个很好的理由是避免更改直接访问属性的250个类。例如,假设我没有使用getter:

class User
{
    public $firstname = 'abc';
    public $lastname  = 'cde';
}

$user = new User(); 

echo $user->firstname . ' ' . $user->lastname;
现在,想象一下,我想改变我的应用程序的行为,并决定将名称打印为大写。在本例中,我将搜索每个实现(在本例中为250:),并在调用属性的任何位置将输出大写。但是,如果我使用了getter,那么我只需要更改getter方法:

class User
{
    private $firstname = 'abc';
    private $lastname  = 'def';

    public getFirstname()
    {
        return ucfirst(strtolower($this->firstname));
    }

    public getLastname()
    {
        return  ucfirst(strtolower($this->lastname));
    }
} 
另外,请记住,getter可能不仅仅从单个属性收集信息。想象一下:

class User
{
    private $id;
    private $firstname;
    private $lastname;

    public function __construct() { some code }

    public function getId() { return $this->id; }

    public function getFirstname() { return $this->firstname; }

    public function setFirstname($value) { $this->firstname = $value; }
}

// And properties are accessed like:
$user->getFirstname();
$user->getId();
class User
{
    private $firstname = 'abc';
    private $lastname  = 'def';

    public function getName()
    {
        return $this->firstname . ' ' . $this->lastname;
    }
}

对于那些对此仍有疑问的人,我建议他们阅读Gordon提供的材料,特别是我链接的答案。

使用访问者满足了他们的需求

引用维基百科:

统一访问原则由Bertrand Meyer提出。它指出“一个模块提供的所有服务都应该通过一个统一的表示法来提供,这并不表明它们是通过存储还是通过计算来实现的。”这一原则通常适用于面向对象编程语言。在更简单的形式中,它指出使用属性、预计算属性或方法/查询之间应该没有区别

在他的博客中

这实际上意味着当事人的客户既不应该知道也不应该关心年龄是否被存储或计算。这为person对象提供了在这两者之间轻松更改的灵活性,并消除了客户端通常不必要的顾虑。它是封装的一个重要部分,或者至少是封装的数据隐藏方面

为了说明这一点,请想象这样一个类:

class Now
{
    public $timestamp;

    public function getTomorrow()
    {
        return strtotime('+1 day', $this->timestamp);
    }

 // … more code
class Now
{
    public $dateTime; // <-- no longer just a timestamp

    public function getTomorrow()
    {
        return strtotime('+1 day', $this->dateTime->getTimestamp());
    }

 // … more code
当您这样做的时候,您就迫使使用该类的开发人员了解实现细节。要获得now的时间戳,开发人员必须

echo $now->timestamp;
echo $now->getTomorrow();
然而,为了获得明天的计算时间戳,开发人员必须

echo $now->timestamp;
echo $now->getTomorrow();
但是开发人员不需要关心,因此如果您想要遵循UAP,您将提供一个访问器来获取时间戳。并通过各种方法将所有的访问渠道

这样做还有一个更稳定的API的额外好处。假设您需要在项目的后面更改实现细节,并将时间戳转换为DateTime对象。您的类现在如下所示:

class Now
{
    public $timestamp;

    public function getTomorrow()
    {
        return strtotime('+1 day', $this->timestamp);
    }

 // … more code
class Now
{
    public $dateTime; // <-- no longer just a timestamp

    public function getTomorrow()
    {
        return strtotime('+1 day', $this->dateTime->getTimestamp());
    }

 // … more code
现在上课
{
public$dateTime;//dateTime->getTimestamp());
}
//…更多代码
现在,任何以前使用
$Now->timestamp
的开发人员都必须更改他们的消费代码以适应这种更改。然而,当您从一开始就使用Getter时,这根本不是问题,因为Getter会确保它返回时间戳。为了进一步证明这一点,请注意开发人员如何不必更改任何内容来使用
getTomorrow()
。虽然我们在内部更改了详细信息,但公共API的行为仍然相同

注意,UAP只是一个指南。现代IDE使为您生成访问器和变异器变得非常容易,因此易于遵循。但这不是绝对的事实。如果你能合理地证明不遵循它,那么就不要遵循它并使用公共属性。但这应该是一个明智的决定


然而,总的来说,(和二传手)无论如何和。这将提供更精简的API。如果您的API有很多getter,那么很可能您正在将真正应该在对象内部的代码分散到使用者中。

当一个变量声明为公共变量时,它可以从任何类访问,使您作为程序员更容易使用;从而解释你想要使用你描述的第二种方法。但是,出于安全原因,某些变量需要声明为私有(有时也被视为一种良好的做法)。我们声明它们为private的事实使它们只能在自己的类中访问。但是,如果您需要在另一个类的函数中使用它们,那么您需要遵循您描述的第一种方法
.

使用getter使其成为只读


(这是概念上的唯一区别。语言可以很容易地根据属性和方法定义接口。命名约定并不是最基本的。)

您应该阅读完整的代码2。它对这个主题和其他软件开发概念有很好的解释。谢谢@Gordon,回答得真不错。我一直在阅读你提供的所有材料。但我还有一个问题。我主要是针对我将要编写的用户类问这个问题。因为它可能有很多属性(比如firstname、lastname、email、hash、created等等),并且考虑到我决定遵循UAP原则,我最终会有很多getter和setter。我相信在这种情况下,如果我避免使用getter和setter,也没有什么不好的,对吗?@SavasVedova如果类只是一个数据结构,那么可能。但我建议不要质疑您是否应该遵循它,而是要质疑为什么您在遵循它时不这样做。未来证明您的代码很容易自动生成它们。