PHP特征:如何规避构造函数或强制它们被调用?

前端之家收集整理的这篇文章主要介绍了PHP特征:如何规避构造函数或强制它们被调用?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
看看以下特点:
trait PrimaryModelRest {

    use RestController;

    protected $primaryModel;

    public function __construct() {
        $mc = $this->getPrimaryModelClass();

        try {
            $this->primaryModel = new $mc();
            if(!($this->primaryModel instanceof Model)) {
                throw new ClassNotFoundException("Primary Model fatal exception: The given Class is not an instance of Illuminate\Database\Eloquent\Model");
            }
        } catch (Exception $e) {
            throw new WrongImplementationException("Primary Model Exception: Class not found.");
        }
    }

    /**
     * @return string: Classname of the primary model.
     */
    public abstract function getPrimaryModelClass();

    // varIoUs functions here

}

正如您所看到的,trait确保using类包含某个模型实例,并且它实现了某些方法.只要实现类不重写构造函数,这就可以工作.

所以这是我的问题:我想确保调用构造函数或更好的解决方案,这样我就可以在初始化时实例化这个模型.

请回答哪些方面多重继承以及es多级继承.

我认为你正在努力使这个特性能够完成它不适合的工作.

特征不是多重继承的形式,而是“水平重用” – 它们通常被描述为“编译器辅助的复制和粘贴”.因此,特征的作用是提供一些代码,这样您就不必手动将其复制到类中.它唯一的关系是发生use语句的类,代码是“粘贴”的.为了帮助这个角色,它可以提出该目标类的一些基本要求,但在此之后,该特征不参与继承.

在您的示例中,您担心子类可能会尝试访问$primaryModel而不运行初始化它的构造函数代码,并且您尝试使用该特征来强制执行该操作;但这实际上不是特质的责任.

Sub类的以下定义完全等效:

trait Test {
    public function foo() {
        echo 'Hello,World!';
    }
}
class ParentWithTrait {
    use Test;
}
class Sub inherits ParentWithTrait {
}

VS:

class ParentWithMethodDefinition {
    public function foo() {
        echo 'Hello,World!';
    }
}
class Sub inherits ParentWithMethodDefinition {
}

在任何一种情况下,类Sub都可以有自己的foo()定义,并绕过你在父类中编写的逻辑.

唯一可以阻止它的合约是final关键字,在你的情况下,这意味着将你的构造函数标记为final.然后,您可以提供一个可以为子类重写的扩展点,以添加它们自己的初始化:

class Base {
    final public function __construct() {
         important_things(); // Always run this!
         $this->onConstruct(); // Extension point
    }
    protected function onConstruct() {
         // empty default definition
    }
}
class Sub {
    protected function onConstruct() {
         stuff_for_sub(); // Runs after mandatory important_things()
    }
}

特征也可以将其构造函数标记为final,但这是要粘贴的代码的一部分,而不是使用特征对类的要求.你实际上可以使用带有构造函数的特征,但是然后编写一个新的构造函数,它会完全掩盖特征的版本:

trait Test {
    final public function __construct() {
        echo "Trait Constructor";
    }
}
class Noisy {
    use Test;
}
class Silent {
    use Test;
    public function __construct() {
        // Nothing
    }
}

就性状而言,这就像买一瓶啤酒并将其倒入水槽:你要求它的代码并没有使用它,但那是你的问题.

但至关重要的是,您还可以为特征的方法添加别名,创建一个具有相同代码但具有不同名称和/或不同可见性的新方法.这意味着您可以混合来自声明构造函数的特征的代码,并在更复杂的构造函数中使用该代码,或者在类中的其他位置使用该代码.

目标类也可能使用“最终挂钩”模式:

trait TestOne {
    final public function __construct() {
        echo "Trait TestOne Constructor\n";
    }
}
trait TestTwo {
    final public function __construct() {
        echo "Trait TestTwo Constructor\n";
    }
}
class Mixed {
    final public function __construct() {
        echo "Beginning\n";
        $this->testOneConstructor();
        echo "Middle\n";
        $this->testTwoConstructor();
        echo "After Traits\n";
        $this->onConstruct();
        echo "After Sub-Class Hook\n";
    }
    use TestOne { __construct as private testOneConstructor; }
    use TestTwo { __construct as private testTwoConstructor; }

    protected function onConstruct() {
        echo "Default hook\n";
    }
}
class ChildOfMixed extends Mixed {
    protected function onConstruct() {
        echo "Child hook\n";
    }
}

该特性并未强制Mixed类实现此模式,但它已启用它,以实现其促进代码重用的目的.

有趣的是,下面的代码不起作用,因为as关键字添加别名,而不是重命名普通方法,所以这最终试图覆盖混合的最终构造函数

class ChildOfMixed extends Mixed {
    use TestTwo { __construct as private testTwoConstructor; }

    protected function onConstruct() {
        $this->testTwoConstructor();
        echo "Child hook\n";
    }
}
原文链接:https://www.f2er.com/php/135392.html

猜你在找的PHP相关文章