声明一个类是不好的做法吗?构造函数“最终”在 PHP 中?

发布于 2024-08-16 13:47:34 字数 568 浏览 9 评论 0原文

如果我有一个由很多其他类扩展的父类,并且我想确保父类的构造函数始终运行,那么声明构造函数 final 是不是一个坏主意?

我正在考虑做这样的事情:

class ParentClass {

    public final function __construct() {

        //parent class initialization...

        $this->construct();

    }

    protected function init() {

        echo 'constructing<br>';

    }

}

class ChildClass extends ParentClass {

    protected function init() {

        //child class initialization

        echo 'constructing child<br>';

    }

}

这样子类可以有一个构造函数,并且父类的构造函数将始终执行。这是不好的做法吗?

If I have a parent class that is extended by lots and lots of other classes, and I want to make sure the parent class's constructor is ALWAYS run, is it a bad idea to declare the constructor final?

I was thinking of doing something like this:

class ParentClass {

    public final function __construct() {

        //parent class initialization...

        $this->construct();

    }

    protected function init() {

        echo 'constructing<br>';

    }

}

class ChildClass extends ParentClass {

    protected function init() {

        //child class initialization

        echo 'constructing child<br>';

    }

}

that way the child class can have a sort-of constructor, and the parent class's constructor will always execute. Is this bad practice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海的爱人是光 2024-08-23 13:47:34

声明 final __construct 确保扩展您的类的任何人都无法实现具有相同名称的方法。从表面上看,这似乎意味着没有其他人可以为此类的子类声明构造函数,但事实并非如此,因为 ClassName() 的 PHP 4 风格作为构造函数的替代名称仍然可以正常工作。所以实际上,在 PHP 中将构造函数声明为 Final 不会给你带来任何好处。

Declaring a final __construct ensures that no one who extends your class can implement a method with the same name. On the surface of it, this would seem like it would mean no one else can declare a constructor for sub-classes of this class, but this is not true, since the PHP 4 style of ClassName() still works just fine as an alternate name for the constructor. So really, declaring a constructor as final gets you nothing in PHP.

夏了南城 2024-08-23 13:47:34

从 PHP 5.3.3 开始,我已经使用 5.6 和 7.0 对此进行了测试,声明类 final__construct 方法将阻止任何子类使用 重写构造函数>__construct 或 PHP 4 样式的 ClassName()(请注意,从 PHP 7 开始,PHP 4 样式已弃用)。防止子类声明构造函数将确保始终调用父构造函数。当然,这将不允许任何子类实现自己的构造函数逻辑。尽管我一般不建议将其作为良好实践,但肯定会有实际用例。

一些例子:

没有声明 __construct Final

class ParentClassWithoutFinal {
    private $value = "default";

    public function __construct() {
        $this->value = static::class;
    }

    function __toString() {
        return $this->value;
    }
}

class ChildClassA extends ParentClassWithoutFinal {
    public function __construct() {
        // Missing parent::__construct();
    }
}

echo (new ChildClassA()); // ouput: default

最后的__construct

class ParentClassWithFinal extends ParentClassWithoutFinal {
    public final function __construct() {
        parent::__construct();
    }
}

class ChildClassB extends ParentClassWithFinal {
}

echo (new ChildClassB()); // output: ChildClassB

尝试在子类中声明__construct

class ChildClassC extends ParentClassWithFinal {
    public function __construct() {
    }
}

// Fatal error: Cannot override final method ParentClassWithFinal::__construct()

尝试在子类中声明 ClassName() 构造函数

class ChildClassD extends ParentClassWithFinal {
    public function ChildClassD() {
    }
}

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD()
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor

As of PHP 5.3.3, I have tested this with 5.6 and 7.0, declaring the __construct method of a class final will prevent any child class overriding the constructor either using __construct or the PHP 4 style of ClassName() (note that the PHP 4 style is deprecated as of PHP 7). Preventing a child class declaring a constructor will ensure that the parent constructor is always called. This will, of course, not allow any child classes to implement their own constructor logic. There would definitely be practical use cases for this though I would not recommend it as good practice generally.

Some examples:

Without declaring __construct final

class ParentClassWithoutFinal {
    private $value = "default";

    public function __construct() {
        $this->value = static::class;
    }

    function __toString() {
        return $this->value;
    }
}

class ChildClassA extends ParentClassWithoutFinal {
    public function __construct() {
        // Missing parent::__construct();
    }
}

echo (new ChildClassA()); // ouput: default

With final __construct

class ParentClassWithFinal extends ParentClassWithoutFinal {
    public final function __construct() {
        parent::__construct();
    }
}

class ChildClassB extends ParentClassWithFinal {
}

echo (new ChildClassB()); // output: ChildClassB

Trying to declare __construct in a child class

class ChildClassC extends ParentClassWithFinal {
    public function __construct() {
    }
}

// Fatal error: Cannot override final method ParentClassWithFinal::__construct()

Trying to declare ClassName() constructor in a child class

class ChildClassD extends ParentClassWithFinal {
    public function ChildClassD() {
    }
}

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD()
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor
桃扇骨 2024-08-23 13:47:34

构造函数完成后,您不能将任何变量传递给初始化函数。它强制您类的用户使用全局变量作为其子类的设置。

在 Zend Framework 中,使用可重写的 init() 是常见的做法,但我从未见过在那里完成构造函数。

After finalizing the constructor, you can't pass any variables to initializing function. It forces users of you class to use globals as settings for their child classes.

In Zend Framework using overridable init() is common practice, but I've never seen finalizing a constructor there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文