web-dev-qa-db-ja.com

__construct()とSameAsClassName()のコンストラクタPHP

PHPでコンストラクターのクラス名の代わりに__construct()を使用する利点はありますか?

例(__construct):

class Foo {
    function __construct(){
        //do stuff
    }
}

例(名前付き):

class Foo {
    function Foo(){
        //do stuff
    }
}

__constructメソッド(最初の例)はPHP 5。

PHPバージョン4からバージョン7まで、コンストラクター(2番目の例)としてクラスと同じ名前のメソッドを持つことが可能です。

67
Newtang

ギズモにも同意します。利点は、クラスの名前を変更しても名前を変更する必要がないことです。ドライ。

同様に、子クラスがある場合は、呼び出すことができます

parent::__construct()

親コンストラクタを呼び出す。トラックのさらに下で子クラスが継承するクラスを変更する場合、親への構成呼び出しを変更する必要はありません。

小さなことのように思えますが、コンストラクターの呼び出し名を親クラスに変更しないと、微妙な(それほど微妙ではない)バグが発生する可能性があります。

たとえば、階層にクラスを挿入したが、コンストラクター呼び出しを変更するのを忘れた場合、親ではなく祖父母のコンストラクターの呼び出しを開始できます。これにより、気づきにくい望ましくない結果が生じることがよくあります。

また注意してください

PHP 5.3.3以降、名前空間クラス名の最後の要素と同じ名前のメソッドはコンストラクタとして扱われなくなります。この変更は非名前空間クラスには影響しません。

ソース: http://php.net/manual/en/language.oop5.decon.php

69
Bazman

__constructはPHP5で導入されました。それはあなたが今それをすることになっている方法です。しかし、私は利点自体には気づいていません。

PHPマニュアルから:

下位互換性のために、PHP 5が特定のクラスの__construct()関数を見つけることができない場合、クラスの名前で古いスタイルのコンストラクター関数を検索します。事実上、互換性の問題が発生する唯一のケースは、クラスに__construct()という名前のメソッドがあり、異なるセマンティクスに使用されている場合です。

PHP5を使用している場合は、__constructを使用して、PHPを他の場所に表示しないようにすることをお勧めします。

20

__constructの主な利点は、クラス名を変更した場合にコンストラクターの名前を変更する必要がないことです。

15
gizmo

今日、受け入れられた答えは時代遅れです。

クラスの名前を変更することは悪い習慣です。新しいバージョンにアップグレードするたびに、何をどこで名前を変更するかを覚えておく必要があります。時々( Reflection または複雑な依存構造を使用するように)根本的なリファクタリングなしでは不可能になる場合があります。そしてこれは 偶然の複雑さ 避けたいものです。 namespacesがPHPに導入されたのはそのためです。 Java、C++またはC#は___construct_を使用せず、名前付きコンストラクターを使用するため、問題はありません。

PHP 5.3.3、namespacedクラス名の最後の要素と同じ名前のメソッドは、この変更は非名前空間クラスには影響しません。

_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
_

名前付きコンストラクタは廃止されていません(現在のPHP 5.5)。ただし、クラスが名前空間で使用されないことを予測することはできないため、そのため___construct_を優先する必要があります。

上記の悪い習慣についての説明(デニスの場合)

コードのどこかで使用できます ReflectionClass :: getName() ;クラスの名前を変更するときは、Reflectionを使用した場所を覚えて、getName()の結果がアプリでまだ一貫しているかどうかを確認する必要があります。特定のことを覚える必要があるほど、忘れられている可能性が高くなり、アプリにバグが発生します。

親は、自分たちに依存する世界のすべてのクラスを制御することはできません。 allow_url_include が有効になっている場合、他のWebがサーバーのクラスを使用している可能性があり、クラスの名前を変更するとクラッシュする可能性があります。上記のコンパイル言語ではさらに悪いことです。ライブラリをコピーして他のコードにバンドルできます。

クラスの名前を変更する理由はありません:

  • クラス名が競合する場合は、名前空間を使用します
  • クラスの責任が変わった場合は、代わりに他のクラスを派生させます

PHP名前空間のクラスでは、とにかく同じ名前のメソッドは避ける必要があります:直感的には、クラスを作成したオブジェクトを生成する必要があります。他に何かする場合、なぜ同じ名前を付けるのですか?主な問題は、そのようなメソッドの動作が名前空間の使用法に依存することです。

PHPの__constructコンストラクターには問題はありません。しかし、名前付きコンストラクターを変更するのは賢明なアイデアではありませんでした。

10
Jan Turoň

あなたの例では、Foo::FooはPHP 4の時代から来ているため、PHP 4または古いスタイルのコンストラクタと呼ばれることがあります。

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

PHP 4コンストラクターは廃止されますが削除されません in PHP 7. PHP 8では、これらはコンストラクターと見なされなくなります。将来の互換性は間違いなく大きいですこの機能を使用しない理由。

7
Levi Morrison

__contruct()の代わりにClassName()を使用する最大の利点は、クラスを拡張するときです。 parent::__construct()の代わりにparent::ClassName()を呼び出す方がはるかに簡単です。クラス間で再利用でき、親を簡単に変更できるためです。

7
Ryan McCue

PHP 5では、パフォーマンスが向上するという利点があります。最初に__constructという名前でコンストラクタを探し、見つからない場合はclassNameという名前のコンストラクターの場合、__constructという名前のコンストラクターが見つかった場合、classNameという名前のコンストラクターを検索する必要はありません。

3
Steven Oxley

さて、この質問を聞いてから数年になりますが、状況は変わったので、読者の皆さんには最新の情報を提供したいと考えています。


そのため、php-7では、クラスと同じ名前の関数としてコンストラクターを作成するオプションが削除されます。それでも行う場合は、_E_DEPRECATED_を取得します。

この提案の詳細(提案は受け入れられます)は、次の場所にあります。 https://wiki.php.net/rfc/remove_php4_constructors

そしてそこからの引用:

PHP 7E_DEPRECATEDを発行しますPHP 4コンストラクタが定義されています。メソッド名がクラス名と一致し、クラスが名前空間になく、PHP 5コンストラクター(__construct)が存在しない場合、E_DEPRECATEDが発行されます。PHP 8はE_DEPRECATEDの発行を停止し、メソッドはコンストラクターとして認識されません。

また、クラスと同じ名前のメソッドと__construct()を定義した場合、php-7では_E_STRICT_を取得できません。

これはここでも見ることができます:

PHP 7は、同じ名前のメソッドがある場合、E_STRICTの発行も停止しますクラスと__constructが存在するためです。


ですから、__construct()を使用することをお勧めします。これで、これに関する問題が少なくなるでしょう。

3
Rizier123

上位互換性。後方互換性のために言語に残されたレガシーコードが将来のバージョンで削除される可能性は常にあります。

2
Jeremy Privett

メソッド__constructとSameAsClassNameメソッドがある場合、__ constructが実行され、SameAsClassNameメソッドはスキップされます。

1
phvish

その主な理由は言語の慣習だと思います。言語を他の人のように動作させる必要はありません。

つまり、Objective-Cでは、たとえばコンストラクタの前に-initを付けます。クラス名を使用して独自のコンストラクタを作成できますが、なぜですか?言語規則の代わりにこのスキーマを使用する理由はありますか?

0
Leonardo Molina