__construct() vs SameAsClassName() for constructor in PHP

后端 未结 11 2638
南笙
南笙 2020-11-28 09:55

Is there any advantage to using __construct() instead of the class\'s name for a constructor in PHP?

Example (__construct):



        
相关标签:
11条回答
  • 2020-11-28 10:11

    I think that the main reason is that is the language convention. You don't need to force a language to act like someone else.

    I mean, in Objective-C you prefix the constructors with -init, for example. You can make your own constructor using your class name but why? Are ther some reason to use this schema instead of the language convention?

    0 讨论(0)
  • 2020-11-28 10:14

    Forward compatibility. There's always a chance that legacy code that's left in the language for backwards compatibility's sake will be removed in a future version.

    0 讨论(0)
  • 2020-11-28 10:20

    I agree with gizmo, the advantage is so you don't have to rename it if you rename your class. DRY.

    Similarly, if you have a child class you can call

    parent::__construct()
    

    to call the parent constructor. If further down the track you change the class the child class inherits from, you don't have to change the construct call to the parent.

    It seems like a small thing, but missing changing the constructor call name to your parents classes could create subtle (and not so subtle) bugs.

    For example, if you inserted a class into your heirachy, but forgot to change the constructor calls, you could started calling constructors of grandparents instead of parents. This could often cause undesirable results which might be difficult to notice.

    Also note that

    As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.

    Source: http://php.net/manual/en/language.oop5.decon.php

    0 讨论(0)
  • 2020-11-28 10:20

    Today, the accepted answer is obsolete.

    Renaming classes is bad practice: you have to remember what and where to rename everytime you upgrade to newer version. Sometimes (like using Reflection or complex dependence structure) it can be impossible without radical refactoring. And this is accidental complexity you want to avoid. That's why namespaces were introduced into PHP. Java, C++ or C# don't use __construct, they use named constructor and there's no issue with them.

    As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.

    Example

    namespace Foo;
    class Test {
      var $a = 3;
    
      function Test($a) {
        $this->a = $a;
      }
    
      function getA() {
        return $this->a;
      }
    }
    
    $test = new Test(4);
    echo $test->getA(); // 3, Test is not a constructor, just ordinary function
    

    Note that named constructors are not deprecated (PHP 5.5 today). However, you can't predict that your class won't be used in namespace, therefore __construct should be preffered.

    Clarification about the bad practice mentioned above (for Dennis)

    Somewhere in your code you could use ReflectionClass::getName(); when you rename the class, you need to remember where you used Reflection and check if the getName() result is still consistent in your app. The more you need to remember something specific, the more likely something is forgotten which results in bugs in the app.

    The parents can't have control about all the classes in the world which depends on them. If allow_url_include is enabled, some other web might be using the class from your server, which may crash if you rename some class. It is even worse in compiled languages mentioned above: the library can be copied and bundled in other code.

    There is no reason why to rename class:

    • if the class name conflicts, use namespaces
    • if the class responsibility shifts, derive some other class instead

    In PHP classes in namespace, the method with the same name should be avoided anyway: intuitively it should produce an object created the class; if it does something else, why to give it the same name? It should be a constructor and nothing else. The main issue is that the behavior of such a method depends on namespace usage.

    There is no issue with __construct constructors in PHP. But it wasn't the smartest idea to alter the named constructors.

    0 讨论(0)
  • 2020-11-28 10:24

    In your example Foo::Foo is sometimes called a PHP 4 or old-style constructor because it comes from the days of PHP 4:

    class Foo {
        // PHP 4 constructor
        function Foo(){
            //do stuff
        }
    }
    

    PHP 4 constructors will be deprecated but not removed in PHP 7. They will be no longer be considered as constructors in any situation in PHP 8. Future compatibility is definitely a big reason to not use this feature.

    0 讨论(0)
提交回复
热议问题