老式和新式PHP构造函数的区别

8
有人能告诉我“旧式”对象构造函数与“新式”构造函数有何不同吗?我正在学习PHP面向对象编程,想要知道何时在阅读旧语法和新语法,并更好地了解PHP OOP随着时间的推移而发生的变化。 新式
class aObject
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}

1
区别在于旧对象使用的是与类名称相同的方法作为构造函数,而新对象使用了一个名为__construct()的“魔术”方法...但旧的已经很旧了,已经被弃用将近10年,现在完全被新方法所取代。 - Mark Baker
1
因为 PHP 网站被封锁了?我们学校要求我们在上网前先阅读教科书。为什么 StackOverflow 没有被封锁,这让我感到困惑。 - White Lotus
4
学校总是让我感到惊讶,不知道他们为什么会做那种傻事。 - JimL
1
代理绕过限制并像应该做的那样阅读PHP手册 - Alex Andrei
2
@WhiteLotus - 不要因为学校的网络阻挡而放弃学习...继续努力学习最好的知识,而不只是你的老师们所限制的。 - Mark Baker
显示剩余6条评论
1个回答

12

"旧"的构造函数语法是指PHP4。PHP4的最后一个版本发布于2008年,而PHP5的第一个版本发布于2004年。这是一个旧式类和新式类的例子。

旧(PHP4)

<?php

class MyOldClass
{
    var $foo;

    function MyOldClass($foo)
    {
        $this->foo = $foo;
    }

    function notAConstructor()
    {
        /* ... */
    }
}

新版本(PHP5+)

<?php

class MyNewClass
{
    var $foo;

    public function __construct($foo)
    {
        $this->foo = $foo;
    }

    public function notAConstructor()
    {
        /* ... */
    }
}

您会注意到这里有几个变化。最显著的变化是构造函数的命名规则已经从ClassName()改为__construct()。这使得所有类的构造函数都有了相同、可预测的名称,这是必要的便利。想象一下,如果您有一个名为ParentClass的类,它有20个子类,每个子类都有自己的构造函数。如果您想从每个子类调用父构造函数,您需要调用ParentClass::ParentClass()。如果您想更改ParentClass的名称,您必须更改所有20个构造函数的调用。但是,使用新方法,您只需要调用parent::__construct(),这总是有效的,即使父类的名称发生更改。

与此变化相关的是,PHP5还引入了类的析构函数__destruct()),当对象被销毁时(相当于构造函数的反向操作)会被调用。

另一个重要的变化是PHP5引入了方法和属性的可见性,它允许对类的方法和属性进行一种“访问控制”。只有标记为public的方法和属性可以从类或其子类之外的上下文中访问。以下是一些示例:

<?php

class StackOverflow
{
    /* This can be accessed from anywhere.
     *
     * You can access it from outside the class:
     *     $so = new StackOverflow();
     *     $so->publicProperty = 10;
     *     echo $so->publicProperty;
     * 
     * Or from inside the class:
     *     $this->publicProperty = 5;
     *     echo $this->publicProperty;
     */
    public $publicProperty = 1;

    /* This can be accessed only from methods inside this class.
     *
     *     $this->privateProperty = 5;
     *     echo $this->privateProperty;
     * 
     * You cannot access it from outside the class, as above.
     * Private properties cannot be accessed from child classes,
     * either.
     */
    private $privateProperty = 2;

    /* This can be accessed only from methods inside this class,
     * OR a child-class.
     *
     *     $this->protectedProperty = 5;
     *     echo $this->protectedProperty;
     * 
     * You cannot access it from outside the class, as with public.
     * You can, however, access it from a child class. 
     */
    protected $protectedProperty = 3;
}

现在,方法的运作方式完全相同。您可以将类中的函数(方法)标记为publicprivateprotected。在PHP4中,所有的类成员都是默认public的。同样,构造函数(__construct())也可以是publicprivateprotected

如果一个类没有包含public构造函数,则它不能被类外的代码实例化(或者,对于protected来说,它的子类也不能)。那么如何使用这样的类呢?当然是使用静态方法

<?php

class ClassWithPrivateConstructor
{
    private $foo;

    private function __construct($foo)
    {
        $this->foo = $foo;
    }

    public static function fromBar($bar)
    {
        $foo = do_something_to($bar);

        return new self($foo);
    }
}

要从其他地方实例化这个类,你需要调用:

$obj = ClassWithPrivateConstructor::fromBar($bar);

当您需要在调用构造函数之前预处理输入或需要使用不同参数的多个构造函数时,这将非常有用。

该方法名称__construct()和其他以__开头的方法名称(如__get()__set()__call()__isset()__unset()__toString()等)被称为magic methods

PHP5带来了许多重大变化,但仍试图保持与PHP4代码的兼容性,因此允许旧式构造函数。

今年发布的PHP7没有更改构造函数语法。 PHP7中与class相关的唯一显着变化是允许使用匿名类(请参见这里)。

从PHP7开始,旧式构造函数已正式弃用(引发错误E_DEPRECATED),并将在PHP8中完全删除。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接