【问题标题】:PHP Check if actual class is implementing interfacePHP 检查实际类是否正在实现接口
【发布时间】:2016-10-13 15:05:21
【问题描述】:

在我正在进行的现有项目中,我们有以下情况:

interface A { }

class B implements A { }

class C extends B { }

class D extends B implements A { }

$B = new B();
$C = new C();
$D = new D();

判断实际类是否实现接口A而不仅仅是父类的正确方法是什么?对于 $B 和 $D,检查应该返回 true,对于 $C,应该返回 false。通常你会这样做

if( $C instanceof A ) { //do the work }

但在我们的情况下,这将返回不应该的 true。

一种方法可以是解析文件并测试该类是否真的使用token_get_all 函数实现了A。但在此之前,我想问一下是否有更优雅的解决方案。

我知道这听起来很奇怪,但情况就是这样,无法更改类层次结构。任何见解都会有所帮助。

【问题讨论】:

  • 如果 B 实现了 A,难道不是所有扩展 B 的类都会自动实现 A 吗?
  • 是的,但我只需要实际具有 implements A 语句的类。给出层次结构是因为它是一个旧的遗留系统。
  • but I need only classes which actually have the implements A statement 你能解释一下吗?
  • 真实世界的场景是我有一个表单字段列表。其中之一是列表表单域。许多其他表单字段确实从该列表字段扩展而来。但我只想要实现 A 的特定的,因为它们在我使用它们的上下文中是有意义的。

标签: php class inheritance interface


【解决方案1】:

仅当接口 A 未通过父类扩展实现时,此函数才返回 true。

echo checkimplements($B, "A"); //Returns True

function checkimplements($class, $interfacename)
{
    $ownInterfaces = class_implements($class);
    $parent = get_parent_class($class);
    if($parent) {
        $parentInterfaces = class_implements($parent);
    } else {
        $parentInterfaces = array();
    }
    $diff = array_diff($ownInterfaces, $parentInterfaces);
    $found = in_array($interfacename, $diff);
    return $found;
}

【讨论】:

  • 但是 D 也返回 false。
【解决方案2】:

找到了这个解决方案:

function implementsInterface($class, string $interface) : bool
{
    $result = $class instanceof $interface;
    if ($result) {
        return true;
    }
    foreach (class_parents($class) as $subClass) {
        if ($result) {
            break;
        }
        $result = implementsInterface($subClass, $interface);
    } 
    return $result;
}

【讨论】:

    猜你喜欢
    • 2010-09-21
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 2018-10-19
    • 2021-01-02
    • 1970-01-01
    相关资源
    最近更新 更多