在 PHP 7.4 里,类属性也可以添加类型了:
class User
{
private int $id;
private ?string $name;
private ArrayObject $groups;
private static int $maxGroups;
}
简单说来就酱。需要注意的是,void 类型和 callable 类型是不可以的(是不是很好奇为啥 callable 不行?)。
看起来此功能只是对属性赋值做了类型的检查(或者转换,非严格模式下),但实际上还是有一些细节,是需要引起大家留意的。
首先,只要给属性设置了类型,那么读取此属性时,如果此属性还没有被初始化(或者说有赋值过),便不再像之前版本一样得到的是 null,而是报 fatal error。
因为属性有了类型之后,没有初始化的带类型属性就不知道自己默认应该是什么值了,所以才添加了这个『无初始化』状态,上面那段话也可以简短说成,『无初始化』状态的属性,被读取的时候会报 fatal error。
而当我们 unset 一个没有类型的属性时,跟以前一样,此属性值会变成 null;但如果我们 unset 一个有类型的属性时,此属性会变成『无初始化』。
其次,设置默认值时,只有显示类型可以为 null 的类型,才可以设置默认值为 null,这跟函数参数的 type hint 有点不一样:
class User
{
private ?string $name = null; // OK
private int $id = 0; // 不行
}
最后,属性类型不能被覆盖。如果清楚 Liskov 替换原则,其实也好理解这个行为
class Bar
{
public int $id;
}
class FooBar
{
public ?int $id; // 不可以
}
为什么这么说呢?其实属性赋值你就可以看成 setter 和 getter。Liskov 替换规定,子类要比父类能处理更大范围的数据(子类方法接受的参数范围更大),但返回的数据要比父类的范围小(子类方法的返回值范围不能大于父类同名方法),无论是子类放大属性的范围(setter 参数满足了,但 getter 返回不满足),还是缩小属性的范围(getter 返回满足了但 setter 参数又不满足),都不符合 Liskov 替换原则。
更多关于 Liskov 替换原则,可以看看这篇文章。
写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人