我的代码在大量归结时看起来很像这样:
abstract class Car {
public abstract static function parts();
protected static function getParts() {
$parts = [];
$properties = (new ReflectionClass(static::class))->getProperties();
foreach ($properties as $property) {
$parts[] = $property->getName();
}
return $parts;
}
}
class Ford extends car {
public $wheels;
public $body;
public static function parts() {
return self::getParts();
}
}
class FordTruck extends Ford {
public $truckBed;
}
function getBaseParts($cartype) {
return $cartype::parts();
}
但是当我打电话给getBaseParts("FordTruck")
时,我回来了
array(3) {
[0]=>
string(8) "truckBed"
[1]=>
string(6) "wheels"
[2]=>
string(4) "body"
}
实际上,我只想回到"轮子"和"身体",而不是过去Ford
课中添加的"无关紧要"的东西。我认为在我关心的部分的类中创建一个parts()
方法,然后调用self::getParts()
,进而从static
获取属性,这意味着"静态"所指的类将是Ford
类。但这更像是在召唤FordTruck
班的parts()
。
有没有办法通过此设置获得我正在寻找的功能?我能想到的"最简单的"方法是将"getParts()"方法移动到Ford
类中,并让它调用自我的反射类,但我有几十个类可以扩展Ford
如果我以这种方式修复它,它们都只是复制的代码。
我不是这个解决方案的粉丝,你宁愿改变你的解决方案背后的心态,但这里有一个简单的解决方案来解决你的问题
<?php
abstract class Car {
public abstract static function parts();
protected static function getParts($class = null) {
return array_keys(get_class_vars($class ?? static::class));
}
}
class Ford extends car {
public $wheels;
public $body;
public static function parts() {
return self::getParts(Ford::class);
}
}
class FordTruck extends Ford {
public $truckBed;
}
function getBaseParts($cartype) {
return $cartype::parts();
}
var_dump(getBaseParts("FordTruck"));
测试 : https://3v4l.org/s8Aar
static::class 总是会返回相关对象实例化的"最低级别"类。因此,static::class 总是会返回 FordTruck,即使它是在 Car 中定义的,并且函数本身是在 Ford 中调用
的。另一方面,self::class 返回它所定义的类的类名。所以福特的self::class将返回福特,即使这个对象在技术上是福特卡车。
获得所需功能的最简单方法是将 self::class 的值从 Ford 传递给 getParts(),并在 Reflection() 中使用它。
因此,例如:
<?php
abstract class Car {
public abstract static function parts();
protected static function getParts(string $className) {
$parts = [];
$properties = (new ReflectionClass($className))->getProperties();
foreach ($properties as $property) {
$parts[] = $property->getName();
}
return $parts;
}
}
class Ford extends Car {
public $wheels;
public $body;
public static function parts() {
return self::getParts(self::class);
}
}
class FordTruck extends Ford {
public $truckBed;
}
function getBaseParts($cartype) {
return $cartype::parts();
}
我设法找到了这个有效的"解决方法",但我不太确定它是最好的解决方案。
abstract class Car {
public static function getParts() {
$carModel = array_reverse(array_values(class_parents(static::class)))[1];
$parts = [];
$properties = (new ReflectionClass(new $carModel))->getProperties();
foreach ($properties as $property) {
$parts[] = $property->getName();
}
return $parts;
}
}
class Ford extends car {
public $wheels;
public $body;
}
class FordTruck extends Ford {
public $truckBed;
}
function getBaseParts($cartype) {
return $cartype::getParts();
}
getBaseParts("FordTruck");