PHPの::(二重コロン)と->(矢印)の違いは何ですか?


196

PHPのメソッドにアクセスする方法は2つありますが、違いは何ですか?

$response->setParameter('foo', 'bar');

そして

sfConfig::set('foo', 'bar');

->変数の関数には(より大記号の付いたダッシュまたはシェブロン)が使用され::、クラスの関数には(二重コロン)が使用されていると想定しています。正しい?

ある=>だけで、配列内のデータを割り当てるために使用される代入演算子?=これは、変数をインスタンス化または変更するために使用される代入演算子とは対照的ですか?



回答:


172

左側がオブジェクトインスタンスの場合は、を使用します->。それ以外の場合はを使用します::

これは、->主にインスタンスメンバーへのアクセスに使用されます(ただし、静的メンバーへのアクセスにも使用できますが、そのような使用は推奨されません)が、::通常は静的メンバーへのアクセスに使用されます(いくつかの特別な場合では、インスタンスメンバーへのアクセスに使用されます) )。

一般的に、::のために使用されるスコープの解像度、それはいずれかのクラス名を有していてもよく、parentself、または(PHP 5.3で)static、その左側に。parent使用されているクラスのスーパークラスのスコープを指します。self使用されるクラスのスコープを参照します。static「呼び出されたスコープ」を指しますレイトスタティックバインディングを参照)。

ルールは、次の::場合に限り、次の場合にのみ、インスタンスコールであるということです。

  • ターゲットメソッドが静的として宣言されておらず
  • 呼び出し時に互換性のあるオブジェクトコンテキストがあります。つまり、これらはtrueでなければなりません。
    1. 呼び出しは、$this存在するコンテキストから行われ、
    2. のクラス$thisは、呼び出されるメソッドのクラスまたはそのサブクラスのいずれかです。

例:

class A {
    public function func_instance() {
        echo "in ", __METHOD__, "\n";
    }
    public function callDynamic() {
        echo "in ", __METHOD__, "\n";
        B::dyn();
    }

}

class B extends A {
    public static $prop_static = 'B::$prop_static value';
    public $prop_instance = 'B::$prop_instance value';

    public function func_instance() {
        echo "in ", __METHOD__, "\n";
        /* this is one exception where :: is required to access an
         * instance member.
         * The super implementation of func_instance is being
         * accessed here */
        parent::func_instance();
        A::func_instance(); //same as the statement above
    }

    public static function func_static() {
        echo "in ", __METHOD__, "\n";
    }

    public function __call($name, $arguments) {
        echo "in dynamic $name (__call)", "\n";
    }

    public static function __callStatic($name, $arguments) {
        echo "in dynamic $name (__callStatic)", "\n";
    }

}

echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";

echo '$b->func_instance():', "\n", $b->func_instance(), "\n";

/* This is more tricky
 * in the first case, a static call is made because $this is an
 * instance of A, so B::dyn() is a method of an incompatible class
 */
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
 * instance of B (despite the fact we are in a method of A), so
 * B::dyn() is a method of a compatible class (namely, it's the
 * same class as the object's)
 */
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";

出力:

B :: $ prop_static:B :: $ prop_static値
B :: func_static():B :: func_static内

$ b-> prop_instance:B :: $ prop_instanceの値
$ b-> func_static():B :: func_static内

$ b-> func_instance():
B :: func_instance
A :: func_instance
A :: func_instance

$ a-> dyn():
A :: callDynamic
動的ダイン(__callStatic)

$ b-> dyn():
A :: callDynamic
動的ダイン(__call)

3
->主にインスタンスメンバーへのアクセスに使用されます(静的メンバーへのアクセスにも使用できますが、そのような使用はお勧めしません)」私はそれが可能であることを知りませんでした。それで、静的メンバーにアクセスするために使用されたときに何らかの方法で「機能」する場合、このように誤って使用した場合の動作の違いは何でしょうか?単なる好奇心から。
ルシダー、2010

4
@lucideer静的メソッドの場合、それは良い方法の問題です(メソッドはクラス自体に属します)が、で静的メソッドを呼び出してもPHPは文句を言いません->。もちろん、静的メソッドを呼び出すためだけにクラスをインスタンス化する必要があるかもしれませんので、パフォーマンスへの影響もあります。ただし、プロパティの場合はさらに問題があります。STRICT警告が発生し、機能する場合と機能しない場合があります。逆も当てはまることに注意してください。インスタンスメソッドを静的に呼び出すことができますが、これはさらに悪いことです($thisそのようなメソッドの実装では使用できません)。
Artefacto 2010

52

::つまり、静的なコンテキストで使用されます。一部のメソッドまたはプロパティが静的として宣言されている場合:

class Math {
    public static function sin($angle) {
        return ...;
    }
}

$result = Math::sin(123);

また、::オペレーター(スコープ解決オペレーター、別名Paamayim Nekudotayim)は、親クラスのメソッド/プロパティを呼び出すときに動的コンテキストで使用されます。

class Rectangle {
     protected $x, $y;

     public function __construct($x, $y) {
         $this->x = $x;
         $this->y = $y;
     }
}

class Square extends Rectangle {
    public function __construct($x) {
        parent::__construct($x, $x);
    }
}

->つまり、動的なコンテキストで使用されます。あるクラスのインスタンスを扱うとき:

class Hello {
    public function say() {
       echo 'hello!';
    }
}

$h = new Hello();
$h->say();

ちなみに、OOPの経験がない場合は、Symfonyを使用することはお勧めできないと思います。


24

実際、このシンボルによって、静的で他の初期化に依存しないクラスメソッドを呼び出すことができます...

class Test {

    public $name;

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

    public static function doWrite($name) {
        print 'Hello '.$name;
    }

    public function write() {
        print $this->name;
    }
}

ここで、doWrite()関数は他のメソッドや変数に依存せず、静的メソッドです。そのため、このクラスのオブジェクトを初期化せずに、この演算子でこのメソッドを呼び出すことができます。

Test::doWrite('Mrinmoy'); // Output: Hello Mrinmoy.

ただしwrite、この方法でメソッドを呼び出すと、初期化に依存するため、エラーが発生します。


15

=>オペレータは、連想配列にキーと値のペアを割り当てるために使用されます。例えば:

$fruits = array(
  'Apple'  => 'Red',
  'Banana' => 'Yellow'
);

これは、foreachステートメントでも同様の意味です。

foreach ($fruits as $fruit => $color)
  echo "$fruit is $color in color.";

14

静的メソッドとインスタンス化されたメソッドおよびプロパティの違いは、PHP 5のOOP PHPを初めて使用する場合の最大の障害の1つであるようです。

静的なコンテキストからオブジェクトまたはプロパティを呼び出す場合、二重コロン演算子(ヘブライ語からPaamayim Nekudotayimと呼ばれます-雑学)が使用されます。これは、オブジェクトのインスタンスがまだ作成されていないことを意味します。

逆に、矢印演算子は、オブジェクトのインスタンスの参照からメソッドまたはプロパティを呼び出します。

静的メソッドは、作成メソッドと削除メソッドのデータベースにリンクされているオブジェクトモデルで特に役立ちます。これは、戻り値を挿入されたテーブルIDに設定し、コンストラクターを使用して行IDでオブジェクトをインスタンス化できるためです。


2

はい、最初にヒットしました'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'。私の悪い、私はそれが$instance::method()あるべきだった$instance->method()。愚かな私。

奇妙なことに、これは私のローカルマシン(PHP 5.3.8を実行)でも問題なく機能します-何もありません。error_reporting= E_ALLの警告もありません-テストサーバーではまったく機能せず、構文エラーで爆発しますブラウザの白い画面。PHPロギングがテストマシンでオフになっていて、ホスティング会社が忙しすぎてオンにすることができなかったため、それほど明白ではありませんでした。

したがって、警告の言葉:明らかに、一部のPHPインストールでは$ instance :: method()を使用できますが、そうでないものもあります。

誰かがその理由を詳しく説明できる場合は、実行してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.