web-dev-qa-db-ja.com

いつ$ this以上selfを使うのですか?

PHP 5では、self$thisの使用の違いは何ですか?

それぞれ適切な場合

1895
Casey Watson

短い答え

現在のオブジェクトを参照するには$thisを使用してください。現在のクラスを参照するにはselfを使用してください。つまり、非静的メンバーには$this->memberを使用し、静的メンバーにはself::$memberを使用します。

全回答

以下は、非静的および静的メンバー変数に対する$thisおよびself正しい使用法の例です。

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

以下は、非静的および静的メンバー変数に対する$thisおよびself誤った使用法の例です。

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

以下はメンバー関数に$thisを使った多態性の例です。

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

以下は、メンバー関数にselfを使用して、多態的な振る舞いを抑制する例です。

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

その考えは、$this->foo()が現在のオブジェクトの正確な型が何であれfoo()メンバー関数を呼び出すということです。オブジェクトがtype Xの場合は、X::foo()を呼び出します。オブジェクトがtype Yの場合、Y::foo()を呼び出します。しかしself :: foo()では、X::foo()が常に呼ばれます。

http://www.phpbuilder.com/board/showthread.php?t=10354489から

投稿者 http://board.phpbuilder.com/member.php?145249-laserlight

1623
John Millikin

キーワードselfは、少なくとも現在のクラスを参照するだけで、静的メンバーに限定するという意味ではありませんNOT。非静的メンバーのコンテキスト内では、selfは現在のオブジェクトのvtableをバイパスする方法も提供します( vtable に関するWikiを参照)。 parent::methodName()を使用して親バージョンの関数を呼び出すことができるのと同じように、self::methodName()を呼び出してメソッドの現在のクラス実装を呼び出すことができます。

class Person {
    private $name;

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

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

これは出力されます:

こんにちは、こんにちは。
Ludwigの人からさよなら

sayHello()$thisポインタを使用するので、vtableがGeek::getTitle()を呼び出すために呼び出されます。 sayGoodbye()self::getTitle()を使用するので、vtableは使用されず、Person::getTitle()が呼び出されます。どちらの場合も、インスタンス化されたオブジェクトのメソッドを処理しており、呼び出された関数内で$thisポインタにアクセスできます。

726
nbeagle

self::を使用しないで、static::を使用してください

言及する価値があるself ::のもう一つの側面があります。迷惑なself::は、実行時ではなく定義時のスコープを指します。 2つのメソッドを持つこの単純なクラスを考えてください。

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

Person::status()を呼び出すと、「Person is alive」と表示されます。これを継承したクラスを作るとどうなるか考えてみましょう。

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

Deceased::status()を呼び出すと、 "Person is alice"と表示されますが、スコープにはself::getStatus()の呼び出しが定義されたときの元のメソッド定義が含まれているため、 "Person is alive"と表示されます。

PHP 5.3には解決策があります。 static::解決演算子は "Late static binding"を実装しています。 status()の行をstatic::getStatus()に変更すると、期待どおりの結果が得られます。 PHPの古いバージョンでは、これを行うためのクラッジを見つける必要があります。

PHPドキュメントを参照してください。

そう質問されていない質問に答えるために...

$this->は現在のオブジェクト(クラスのインスタンス)を表し、static::はクラスを表します

445
Sqoo

self$thisについて話しているときに何を話しているのかを本当に理解するには、実際に概念的および実用的なレベルで何が起こっているかを掘り下げる必要があります。私は本当に答えがこれを適切に行うとは思わないので、ここに私の試みがあります。

classおよびobjectが何であるかについて話を始めましょう。

クラスとオブジェクト、概念的に

それで、 is aclass?多くの人は、オブジェクトに対してblueprintまたはtemplateとして定義しています。実際、もっと読むことができます PHPここのクラスについて 。そして、ある程度までそれは実際にそうです。クラスを見てみましょう:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

おわかりのように、そのクラスには$nameという名前のプロパティとsayHello()という名前のメソッド(関数)があります。

veryは、classが静的構造であることに注意することが重要です。つまり、クラスPersonは、一度定義されると、どこで見ても常に同じです。

一方、オブジェクトは、クラスのinstanceと呼ばれるものです。つまり、クラスの「設計図」を取得し、それを使用して動的コピーを作成します。このコピーは、保存されている変数に明確に関連付けられています。したがって、instanceへの変更は、そのインスタンスに対してローカルです。

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

new演算子を使用して、クラスの新しいinstancesを作成します。

したがって、クラスはグローバル構造であり、オブジェクトはローカル構造であると言います。面白い->構文について心配する必要はありません。少し詳しく説明します。

話すべきもう1つのことは、インスタンスがinstanceof特定のクラスである場合、checkできることです。ブール値を返す$bob instanceof Person$bobインスタンスがPersonクラスを使用して作成された場合、orPersonの子。

状態の定義

それでは、クラスに実際に含まれているものを少し掘り下げてみましょう。クラスに含まれる「もの」には5つのタイプがあります。

  1. Properties-これらは、各インスタンスに含まれる変数と考えてください。

    class Foo {
        public $bar = 1;
    }
    
  2. Static Properties-これらをクラスレベルで共有される変数と考えてください。つまり、各インスタンスによってコピーされることはありません。

    class Foo {
        public static $bar = 1;
    }
    
  3. Methods-これらは、各インスタンスに含まれる(およびインスタンスで動作する)関数です。

    class Foo {
        public function bar() {}
    }
    
  4. Staticメソッド-これらはクラス全体で共有される関数です。それらはインスタンスに対して not 操作を行いますが、代わりに静的プロパティのみに対して操作します。

    class Foo {
        public static function bar() {}
    }
    
  5. Constants-クラスは定数を解決しました。ここでは詳しく説明しませんが、完全を期すために追加します。

    class Foo {
        const BAR = 1;
    }
    

基本的に、情報が共有されている(したがって静的である)かどうかを識別するstaticについての「ヒント」を使用して、クラスおよびオブジェクトコンテナーに情報を格納していますしたがって動的)。

状態と方法

メソッドの内部では、オブジェクトのインスタンスは$this変数で表されます。そのオブジェクトの現在の状態があり、プロパティを変更(変更)すると、そのインスタンスが変更されます(他のインスタンスは変更されません)。

メソッドが静的に呼び出される場合、$this変数は定義されません。これは、静的呼び出しに関連付けられたインスタンスがないためです。

ここで興味深いのは、静的呼び出しがどのように行われるかです。状態にアクセスする方法について説明しましょう。

状態へのアクセス

その状態を保存したので、それにアクセスする必要があります。これには少し注意が必要です(または way 少し以上)、インスタンス/クラスの外部から(たとえば、通常の関数呼び出しから、または(グローバルスコープから)、およびインスタンス/クラス内(オブジェクトのメソッド内から)。

インスタンス/クラスの外部から

インスタンス/クラスの外側から見ると、ルールは非常にシンプルで予測可能です。 2つの演算子があり、それぞれがインスタンスまたはクラスstaticを処理しているかどうかをすぐに通知します。

  • ->-object-operator-これは、インスタンスにアクセスするときに常に使用されます。

    $bob = new Person;
    echo $bob->name;
    

    Person->fooの呼び出しは意味をなさないことに注意することが重要です(Personはインスタンスではなくクラスであるため)。したがって、それは解析エラーです。

  • ::-scope-resolution-operator-これは、クラスの静的プロパティまたはメソッドにアクセスするために常に使用されます。

    echo Foo::bar()
    

    さらに、同じ方法でオブジェクトの静的メソッドを呼び出すことができます。

    echo $foo::bar()
    

    extremelyは、これを outside から行うと、オブジェクトのインスタンスがbar()から隠されることに注意することが重要です。方法。実行とまったく同じという意味です:

    $class = get_class($foo);
    $class::bar();
    

したがって、$thisは静的呼び出しで定義されていません。

インスタンス/クラスの内部から

ここで状況は少し変わります。同じ演算子が使用されますが、それらの意味はかなりあいまいになります。

object-operator->は、オブジェクトのインスタンス状態の呼び出しに引き続き使用されます。

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

オブジェクト演算子bar()を使用して$fooFooのインスタンス)で$foo->bar()メソッドを呼び出すと、$aのインスタンスのバージョンが生成されます。

それが私たちが期待する方法です。

ただし、::演算子の意味は変わります。現在の関数の呼び出しのコンテキストに依存します。

  • 静的コンテキスト内

    静的コンテキスト内では、::を使用して行われた呼び出しも静的になります。例を見てみましょう:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    Foo::bar()を呼び出すと、baz()メソッドが静的に呼び出されるため、$this not に設定されます。最近のバージョンのPHP(5.3+)では、静的ではないメソッドを呼び出しているため、E_STRICTエラーが発生することに注意してください。

  • インスタンスコンテキスト内

    一方、インスタンスコンテキスト内では、::を使用して行われる呼び出しは、呼び出しの受信者(呼び出しているメソッド)に依存します。メソッドがstaticとして定義されている場合、静的呼び出しを使用します。そうでない場合は、インスタンス情報を転送します。

    したがって、上記のコードを見て、$foo->bar()を呼び出すと、trueが返されます。これは、「静的」呼び出しがインスタンスコンテキスト内で発生するためです。

理にかなっていますか?そうは思わなかった。ややこしい。

ショートカットキーワード

クラス名を使用してすべてを結び付けるのはかなり面倒なので、PHPはスコープを簡単に解決するための3つの基本的な「ショートカット」キーワードを提供します。

  • self-これは現在のクラス名を指します。 self::baz()は、Fooクラス(その上の任意のメソッド)内のFoo::baz()と同じです。

  • parent-これは、現在のクラスの親を指します。

  • static-これは、呼び出されたクラスを指します。継承のおかげで、子クラスはメソッドと静的プロパティをオーバーライドできます。したがって、クラス名の代わりにstaticを使用してそれらを呼び出すと、現在のレベルではなく、呼び出し元を解決できます。

これを理解する最も簡単な方法は、いくつかの例を見てみることです。クラスを選んでみましょう:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

さて、ここでも継承を見ています。これが悪いオブジェクトモデルであることをしばらく無視しますが、これで遊んだときに何が起こるか見てみましょう。

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

そのため、IDカウンターはインスタンスと子の両方で共有されます(selfを使用してアクセスするためです。staticを使用すると、子クラスでオーバーライドできます)。

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

毎回Person::getName()instanceメソッドを実行していることに注意してください。ただし、いずれかのケース(子ケース)でparent::getName()を使用しています。これがこのアプローチを強力にするものです。

注意点#1

呼び出しコンテキストは、インスタンスが使用されるかどうかを決定するものであることに注意してください。したがって:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

always trueではありません。

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

ここでreallyが変わっています。別のクラスを呼び出していますが、Foo::isFoo()メソッドに渡される$this$barのインスタンスです。

これは、あらゆる種類のバグと概念的なWTF-eryを引き起こす可能性があります。したがって、3つの仮想「ショートカット」キーワード(staticself、およびparent)を除くすべてのインスタンスメソッドで、::演算子を使用しないことを強くお勧めします。 。

注意点2

静的メソッドとプロパティは全員で共有されることに注意してください。それは基本的にそれらをグローバル変数にします。グローバルに伴うすべての同じ問題で。したがって、情報が本当にグローバルであることに慣れていない限り、静的なメソッド/プロパティに情報を格納することをためらいます。

注意点#3

一般に、staticの代わりにselfを使用して、遅延静的バインディングと呼ばれるものを使用する必要があります。しかし、それらは同じものではないので、「staticの代わりに常にselfを使用する」というのは本当に近視眼的であることに注意してください。static resolve呼び出しをオーバーライドできる子クラス。

TL/DR

残念ですが、戻って読んでください。長すぎるかもしれませんが、これは複雑なトピックなので長すぎます

TL/DR#2

いいよ。つまり、selfはクラス内の現在のクラス名を参照するために使用されます。ここで、$thisは現在のオブジェクトを参照しますinstanceselfはコピー/貼り付けのショートカットであることに注意してください。クラス名で安全に置き換えることができ、正常に機能します。しかし、$thisは動的変数であり、事前に決定することはできません(クラスでさえない場合があります)。

TL/DR#3

オブジェクト演算子(->)が使用されている場合、alwaysインスタンスを処理していることがわかります。 scope-resolution-operatorが使用されている場合(::)、コンテキストに関する詳細情報が必要です(すでにオブジェクトコンテキストにいますか?オブジェクトの外にいますか?など)。

241
ircmaxell

self($ selfではない)はクラスのを表します。ここで、$thisは現在のインスタンスを表しますクラスのselfは、静的メンバー関数に使用して、静的メンバー変数にアクセスできるようにするためのものです。 $thisは非静的メンバ関数で使用され、メンバ関数が呼び出されたクラスのインスタンスへの参照です。

thisはオブジェクトなので、次のように使用します。$this->member

selfはオブジェクトではないので、基本的には現在のクラスを自動的に参照する型です。self::memberのように使用します。

115
MrZebra

$this->は、クラスの変数(メンバ変数)またはメソッドの特定のインスタンスを参照するために使用されます。

Example: 
$derek = new Person();

$ derekはPersonの特定のインスタンスになりました。すべてのPersonにはfirst_nameとlast_nameがありますが、$ derekには特定のfirst_nameとlast_nameがあります(Derek Martin)。 $ derekインスタンスの中では、それらを$ this-> first_nameおよび$ this-> last_nameとして参照できます。

ClassName ::はそのタイプのクラス、およびその静的変数、静的メソッドを指すために使用されます。それが助けになれば、あなたは精神的に "静的"という言葉を "共有"に置き換えることができます。これらは共有されているので、$ thisを参照することはできません。これは特定のインスタンスを参照します(共有されていません)。静的変数(つまり、静的$ db_connection)は、ある種類のオブジェクトのすべてのインスタンス間で共有できます。たとえば、すべてのデータベースオブジェクトは単一の接続(static $ connection)を共有します。

静的変数例:単一のメンバ変数を持つデータベースクラスがあるとしましょう。static $ num_connections;それでは、これをコンストラクタに入れてください。

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

オブジェクトがコンストラクタを持っているのと同じように、それらはデストラクタも持っています。そして、それはオブジェクトが死ぬか、または設定解除されるときに実行されます:

function __destruct()
{
    $num_connections--;
}

新しいインスタンスを作成するたびに、接続カウンタが1つ増えます。インスタンスを破棄または使用を停止するたびに、接続カウンタが1つ減少します。このようにして、使用しているデータベースオブジェクトのインスタンス数を監視できます。

echo DB::num_connections;

$ num_connectionsは静的(共有)なので、アクティブなデータベースオブジェクトの総数を反映します。データベースクラスのすべてのインスタンス間でデータベース接続を共有するためにこの手法が使用されているのを見たことがあるかもしれません。データベース接続の作成には長い時間がかかるため、これを行うのは、ただ1つ作成してそれを共有するのが最善の方法です(これをシングルトンパターンと呼びます)。

静的メソッド(すなわち、public static View :: format_phone_number($ digits))は、それらのオブジェクトのうちの1つを最初にインスタンス化することなく使用することができます(すなわち、内部的に$ thisを参照しません)。

静的メソッドの例:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

ご覧のとおり、public static function prettyNameはオブジェクトについて何も知りません。オブジェクトの一部ではない通常の関数のように、渡されたパラメータを使用しているだけです。それでは、それをオブジェクトの一部としてではなくても構わないとしたら、なぜ迷惑なのでしょうか。

  1. まず、オブジェクトに関数を添付することで物事を整理しやすくなり、それらを見つける場所がわかります。
  2. 次に、名前の競合を防ぎます。大規模プロジェクトでは、2人の開発者がgetName()関数を作成することになるでしょう。一方がClassName1 :: getName()を作成し、もう一方がClassName2 :: getName()を作成しても、まったく問題ありません。衝突はありません。はい、静的メソッドです。

SELF ::コーディングしている場合outside必要な静的メソッドを持つオブジェクトを参照してください、あなたはオブジェクトの名前を使用してそれを呼び出す必要がありますView :: format_phone_number($ phone_number);inside参照したい静的メソッドを持つオブジェクトをコーディングしている場合は、bothuseオブジェクトの名前View :: format_phone_number($ pn)、OR self :: format_phone_number($ pn)のショートカットを使用できます。

同じことが静的変数にも言えます:例:View :: templates_pathとself :: templates_path

DBクラスの内部で、他のオブジェクトの静的メソッドを参照している場合は、オブジェクトの名前を使用します。例:Session :: getUsersOnline( ;

しかし、DBクラスがそれ自身の静的変数を参照したい場合、それは単にselfを言うでしょう:例:self :: connection;

それが物事をクリアするのに役立ちます願っています:)

96
lo_fye

このブログ投稿から:

  • selfは現在のクラスを参照します
  • selfは、静的関数を呼び出して静的メンバー変数を参照するために使用できます。
  • selfは静的関数内で使用できます
  • selfはvtableを迂回することで多態性の振る舞いを止めることもできます
  • $thisは現在のオブジェクトを参照します
  • $thisは静的関数を呼び出すために使用できます
  • $thisを静的メンバ変数の呼び出しに使用しないでください。代わりにselfを使用してください。
  • $thisは静的関数内では使用できません
29
okconfused

PHPでは、selfキーワードを使用して静的プロパティと静的メソッドにアクセスします。

問題は、$this->method()がstaticとして宣言されているかどうかにかかわらず、self::method()method()anywhereに置き換えることができるということです。それで、あなたはどれを使うべきですか?

このコードを見てください:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

この例では、self::who()は常に「parent」を出力しますが、$this->who()はオブジェクトのクラスによって異なります。

$thisは現在のオブジェクトのクラスを参照していますが、selfはそれが呼び出されているクラスを参照しています。

そのため、$thisが利用できない場合、または下位クラスが現在のメソッドを上書きできないようにする場合にのみ、selfを使用してください。

25
ramin rostami

クラス定義内では、$ thisは現在のオブジェクトを参照し、selfは現在のクラスを参照します。

Selfを使用してクラス要素を参照し、$ thisを使用してオブジェクト要素を参照する必要があります。

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
21
Tarun Singhal

これは、非静的および静的メンバー変数に対する$ thisおよびselfの正しい使用例です。

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?> 
20
Mohit Bumb

によると http://www.php.net/manual/en/language.oop5.static.php$selfはありません。現在のクラスのインスタンス(オブジェクト)を参照するための$thisと、クラスの静的メンバーを参照するために使用できるselfだけがあります。ここでは、オブジェクトインスタンスとクラスの違いが出てきます。

20
cruizer

selfは現在のクラスを参照します

$thisは現在のオブジェクトを参照します。あなたはselfの代わりにstaticを使うことができます。例を見てください。

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

出力:親子

15
Kabir Hossain

ClassName::staticMemberを呼び出してクラスの静的メンバーを呼び出すことができるかどうかは問題ではないと思います。 self::classmember$this->classmemberを使うことの違いは何ですか。

たとえば、self::$this->のどちらを使用しても、次の例はどちらもエラーなく動作します。

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}
14
dr evil

ここでだれも公演について話していなかったので、ここに私がした小さなベンチマークがあります(5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

これらは2 000 000実行の結果です、そしてこれが私が使ったコードです:

<?php

require '../vendor/autoload.php';

// My small class to do benchmarks
// All it does is looping over every test x times and record the
//   time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();
14
tleb
  • オブジェクトポインタ$ thisは、現在のオブジェクトを参照します。
  • クラス値 "static"は現在のオブジェクトを表します。
  • クラス値 "self"は、それが定義されたクラスそのものを指します。
  • クラス値 "parent"は、それが定義されていたクラスそのものの親を指します。

過負荷を示す次の例を参照してください。

<?php

class A {

    public static function newStaticClass()
    {
        return new static;
    }

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

ほとんどの場合、現在のクラスを参照したいので、staticまたは$thisを使用します。ただし、needselfのように拡張しても元のクラスが必要なため、必要な場合があります。 (非常に、非常にまれ)

14
Xeoncross

self::演算子と一緒に使用されるとき、それは現在のクラスを参照します。これは、静的コンテキストでも非静的コンテキストでも行うことができます。 $thisはオブジェクトそのものを参照します。さらに、静的メソッドを呼び出すために$thisを使用することは完全に合法です(ただし、フィールドを参照することはできません)。

13
mrDjouk

$thisは現在のクラスオブジェクトを表し、selfは現在のクラスを表します(オブジェクトではありません)。クラスはオブジェクトの青写真です。だからあなたはクラスを定義するが、あなたはオブジェクトを構築する。

つまり、self for staticthis for none-static members or methodsを使用してください。

また、子/親シナリオでは、self / parentは主に子クラスと親クラスのメンバーとメソッドを識別するために使用されます。

7
Rakesh Singh

さらに、$this::についてはまだ議論されていません。

情報提供のみを目的として、PHP 5.3以降、static::を使用するのではなく、インスタンス化されたオブジェクトを処理して現在のスコープ値を取得するときに、代わりに$this::を使用できます。

http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

上記のコードの使用は一般的でも推奨されるプラクティスでもありませんが、単にその使用法を説明するためのものであり、「ご存知ですか?」元のポスターの質問に関連して。

また、$object::CONSTANTではなく、echo $foo::NAME;などの$this::NAME;の使用法も表します。

7
fyrye

私は同じ質問に出くわした、そして簡単な答えは:

  • $ thisはクラスのインスタンスを必要とします
  • self ::はしません

静的メソッドまたは静的属性を使用していて、クラスのオブジェクトをインスタンス化せずにそれらを呼び出したい場合は、必ず使用する必要がありますself ::を呼び出すには、$ thisを作成するには常にオブジェクトが必要です。

5
Mike

そのクラスのオブジェクト/インスタンスを作成せずにそのクラスのメソッドを呼び出したい場合はselfを使用してください。したがって、 RAM を節約できますその目的)。つまり、実際にはメソッドを静的に呼び出しています。オブジェクトの観点からthisを使用してください。

5
minhajul

ケース1:使用selfはクラス定数に使用できます

 class classA {
 const FIXED_NUMBER = 4; 
 self :: POUNDS_TO_KILOGRAMS 
} 

クラス外で呼び出したい場合は、classA::POUNDS_TO_KILOGRAMSを使用して定数にアクセスします。

ケース2:静的プロパティ

クラスclassC {
パブリック関数__construct(){
 self :: $ _ counter ++; $ this-> num = self :: $ _ counter; 
} 
} 
2
li bing zhao

Php.netによると、この文脈には3つの特別なキーワードがあります:selfparentおよびstatic。それらはクラス定義の中からプロパティやメソッドにアクセスするために使われます。

一方、$thisは、そのクラスがアクセス可能である限り、任意のクラスのインスタンスとメソッドを呼び出すために使用されます。

1
Fil