its-mieger / obj
用于实现对象原生数据类型行为(比较、转换...)的库
Requires
- php: >=7.0
Requires (Dev)
- phpunit/phpunit: ^8.5
README
此库有助于实现类似于原生数据类型(类型转换、比较、转换、运算符重载...)的自定义PHP对象的行为。
由于PHP不支持运算符重载,因此实现了自定义辅助函数来应用使用实现的行为的操作。
以下接口可用
辅助函数
由于PHP不支持运算符重载,必须使用特殊辅助函数使对象的行为符合指定的接口。但是辅助函数不会自动加载,但可以通过调用 Obj::loadHelpers() 来导入。如果没有加载,可以通过调用 Obj 类的静态方法来调用辅助函数。
行为
使用其中一个对象辅助函数,对象的行为将像原生数据类型对应的原生运算符那样。
示例
class MyInt implements CastsAsInteger {
public function toInt(): int {
return 3;
}
}
$a = new MyInt();
$result = op_add($a, 2);
在此示例中,$result 将为 5。向对象添加整数将调用 toInt()-函数将对象转换为整数,然后执行操作。
重要 您不应该在一个类中实现超过一个 CastsAs*-接口。否则,对象可能会表现出意外的行为,例如在某些情况下可能转换为 int,而在其他情况下转换为 float。而不是实现两个接口,您应该仅实现例如 int。如果需要浮点值,返回的整数值将自动转换为 float。
重写运算符
有时转换对象是不够的。想象一个自定义的Money实现,您想要添加两个Money对象,并希望得到一个新的Money对象而不是一个标量数字。因此,您可以实现一个 Operator*-接口并定义自己的运算符。
运算符如何应用
有时不清楚哪个运算符函数被调用。特别是当有两个对象实现相同的运算符时。下面描述的行为涉及 Operator*-接口以及覆盖所有比较运算符的一个函数的 Comparable-接口。
-
如果两个都实现了运算符接口,如果对象是后代且操作是交换的(比较操作也被视为交换的),则运算符函数为后代对象调用。如果对象不是后代,则运算符函数为左侧对象调用。
-
如果只有一个实现了Operator接口,则运算符函数为相应的对象调用。
-
如果没有实现运算符接口,则将对象转换为它们的原生表示,并应用原生运算符。
测试
您可以通过创建一个用于 ObjectHelper 类的模拟对象并将其传递给 Obj::mock(...) 来模拟辅助函数。这样,所有对对象辅助函数的调用(通过辅助函数或静态接口)都将重定向到模拟对象。调用 Obj::resetMock() 以删除模拟对象并再次使用对象逻辑。