php - PHP对象比较和私有属性
问题描述
我想知道 PHP 如何确定具有私有属性的类实例的相等性:
class Example {
private $x;
public $y;
public __construct($x,$y) {
$this->x = $x; $this->y = $y;
}
}
和类似的东西
$needle = new Example(1,2);
$haystack = [new Example(2,2), new Example(1,2)];
$index = array_search($needle, $haystack); // result is 1
结果确实是 1,所以比较私有成员。是否有可能只匹配公共属性?
我知道我可以覆盖该__toString
方法并将所有数组和指针转换为字符串,但这会导致代码难看。
我希望找到一个足够优雅的解决方案,可以使用in_array
, array_search
,array_unique
等。
解决方案
一个可能的解决方案可能是 PHP 反射 API。考虑到这一点,您可以读取一个类的公共属性并将它们与同一类的另一个实例的其他公共属性进行比较。
下面的代码是公共类属性的简单对比。比较的基础是一个简单的值对象。
declare(strict_types=1);
namespace Marcel\Test;
use ReflectionClass;
use ReflectionProperty;
class Example
{
private string $propertyA;
public string $propertyB;
public string $propertyC;
public function getPropertyA(): string
{
return $this->propertyA;
}
public function setPropertyA(string $propertyA): self
{
$this->propertyA = $propertyA;
return $this;
}
public function getPropertyB(): string
{
return $this->propertyB;
}
public function setPropertyB($propertyB): self
{
$this->propertyB = $propertyB;
return $this;
}
public function getPropertyC(): string
{
return $this->propertyC;
}
public function setPropertyC($propertyC): self
{
$this->propertyC = $propertyC;
return $this;
}
public function __compare(Example $b, $filter = ReflectionProperty::IS_PUBLIC): bool
{
$reflection = new ReflectionClass($b);
$properties = $reflection->getProperties($filter);
$same = true;
foreach ($properties as $property) {
if (!property_exists($this, $property->getName())) {
$same = false;
}
if ($this->{$property->getName()} !== $property->getValue($b)) {
$same = false;
}
}
return $same;
}
}
该类的__compare
方法Example
使用PHP Reflection API。首先,我们构建一个我们想要与当前实例进行比较的类的反射实例。然后我们请求我们想要比较的类的所有公共属性。如果实例中不存在公共属性,或者该属性的值与我们要比较的对象中的不同,则该方法返回 false,否则返回 true。
一些例子。
$objectA = (new Example())
->setPropertyA('bla')
->setPropertyB('yadda')
->setPropertyC('bar');
$objectB = (new Example())
->setPropertyA('foo')
->setPropertyB('yadda')
->setPropertyC('bar');
$result = $objectA->__compare($objectB);
var_dump($result); // true
在此示例中,比较结果true
是因为公共属性存在于两个实例中并且具有相同的值PropertyB
。PropertyC
请记住,只有当第二个实例是同一个类时,这种比较才有效。人们可以进一步旋转这个解决方案,并根据它们的特性比较所有可能的对象。
数组过滤器示例
它是一种in_array
基于所示__compare
方法的功能重建。
declare(strict_types=1);
namespace Marcel\Test;
class InArrayFilter
{
protected ArrayObject $data;
public function __construct(ArrayObject $data)
{
$this->data = $data;
}
public function contains(object $b)
{
foreach ($this->data as $object) {
if ($b->__compare($object)) {
return true;
}
}
return false;
}
}
这个过滤器类的作用类似于in_array
函数。它需要一个对象集合并检查集合中是否存在具有相同公共属性的对象。
结论
如果您希望此解决array_unique
方案像array_search
ìn_array
__compare
这取决于要处理的数据量和回调方法的性能。应用程序可能会消耗更多内存,因此变得更慢。
推荐阅读
- travis-ci - Travis-CI - 铬 62 而不是 77
- kotlin - 使用 by 委托给另一个相同类型的对象甚至不会编译
- python - 有什么方法可以在 django settings.py 中导入模型?
- javascript - 如何在查询参数中使用 plus 而不是 %20 和 vue 路由器?
- azure - Azure Webjob/函数重试计数
- python - __init__() 接受 2 个位置参数,但 3 个是使用 WebDriverWait 和 expected_conditions 作为 element_to_be_clickable 和 Selenium Python 给出的
- mysql - 插入查询是否需要三个引号?
- jsf - 在前端的下拉列表和搜索框中键入适当的搜索
- javascript - 如何在 alasql 中按日期配置查询条件。谷歌脚本 + AlaSql
- serialization - 无法序列化值。错误:格式错误的 UTF-8 字符,可能编码不正确