提问人:Leo Galleguillos 提问时间:12/25/2022 最后编辑:Leo Galleguillos 更新时间:12/25/2022 访问量:228
在php中,确定是否设置私有属性的好方法是什么?[关闭]
In php, what is a good way to determine whether private property is set? [closed]
问:
请考虑以下用户类:
<?php
class User
{
private string $name;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
$user = new User();
我们想得到 object 的属性。但是,该属性并不总是设置。如果我们运行并且尚未设置该属性,则会收到以下警告:$name
$user
$name
$user->getName()
$name
PHP Warning: Uncaught Error: Typed property User::$name must not be accessed before initialization
我们怎样才能在不遇到错误的情况下调用?$user->getName()
使用__isset
?
我们应该使用神奇的方法吗?例如,我们可以将以下方法添加到类中:__isset
__isset
public function __isset($name): bool {
return isset($this->$name);
}
然后,从课堂外,我们可以运行:
if (isset($user->name)) {
// $user->getName() can now be called
}
但是,我们的代码包含事先知道该属性是私有的,这似乎很奇怪。此外,由于我们经常调用该属性,因此我们会在代码中的许多(可能数百个)位置添加此语句。$user->name
$name
$name
if
默认$name
为 null?
例如,我们可以更新我们的类:
class User
{
private ?string $name = null;
public function getName(): ?string
{
return $this->name;
}
// ...
}
然后,从课堂外,我们可以运行:
if (isset($user->getName())) {
// Do stuff ...
}
但是,默认为 since 不是某人姓名的有效值似乎很奇怪。“未初始化”的值似乎更合适。而且,我们还需要在代码周围添加大量语句。$name
null
null
if
任何建议或反馈将不胜感激。谢谢。
答:
我想到了四种方式:
- 定义时初始化$name
- 强制构造函数初始化$name
- 签入
getName()
- 添加帮助程序方法
class User
{
// either pre-initialize
private string $name = '';
// or enforce setting by constructor
public function __construct(string $name = '')
{
$this->name = $name;
}
public function getName(): string
{
// or check within getName(), null-coalescing operator added as suggested by Robert in a comment
return $this->name ?? '';
}
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
// or add a public helper function
public function isNameSet(): bool
{
return (isset($this->name));
}
}
$user = new User();
if ($user->isNameSet()) {
// Do things
}
使用非类型化属性,或在构造函数中初始化它,或者使用属性的声明来初始化它。
整个要点或类型化属性是避免与 null 进行比较(嗯,这是要点之一)。此外,null 不是字符串。因此,使用 null/or-string 类型或多或少会破坏整个观点 - 您也可以改用非类型化属性。
在php中,确定是否设置私有属性的好方法是什么?
恕我直言,你的心态是错误的。在 OOP 范式中,你有责任正确地初始化你的对象,而不是在实例化后问“我的对象是否初始化了?
所以答案是:正确初始化它,或者声明一个默认值。
GLHF系列
评论
避免在整个系统中使用条件检查可能很困难,因为您的系统似乎需要值,但这些值并不总是可用,并且取决于调用您的位置使用返回值的方式。valid
getters
如果你愿意进行一些修改,那么你可以按照你的建议,使某些属性可以为空,或者用合适的值初始化它们(,,任何适合你的业务/用例)。正如Nigel 任在他的评论中提到的,根据场景,一个值可以是完全有效的(尽管它可能并不理想)。User
null
empty
null
以下内容可能对您有所帮助,尽管它并不能完全减轻执行条件检查的要求。它确实提供了一些(可以说)更简单的帮助程序方法来执行此类检查并返回一些默认值。
class User
{
private ?string $name = null;
private ?string $nickname = '';
private ?string $city = 'New York';
public function getName()
{
return $this->name !== null && !empty($this->name)
? $this->name
: "Not Provided";
}
public function getNickName()
{
return $this->nickname !== null && !empty($this->nickname)
? $this->nickname
: "Not Provided";
}
public function getCity()
{
return $this->city !== null && !empty($this->city)
? $this->city
: "Not Provided";
}
public function uninitialised()
{
$uninitialized = [];
foreach (get_object_vars($this) as $property => $value) {
if (!isset($value) || empty($value)) {
$uninitialized[] = $property;
}
}
return $uninitialized;
}
public function checkForUninitialised(array $properties)
{
return array_intersect($properties, $this->uninitialised());
}
}
$user = new User();
var_dump($user->uninitialised());
echo PHP_EOL;
var_dump(
$user->checkForUninitialised(
['name', 'nickname', 'city'],
$user->uninitialised()
)
);
上述结果为:
array(2) {
[0]=>
string(4) "name"
[1]=>
string(8) "nickname"
}
array(2) {
[0]=>
string(4) "name"
[1]=>
string(8) "nickname"
}
评论
__get()
getProperty
__get()
评论
name
Users
$name
$name
$nickname
$city
User
User
$this->name ?? '';