これは興味深い質問ですので、私は小さな研究を掘り下げました。実際にあなたが作る呼び出しのいくつかはドキュメントに従って動作しますが、実生活ではまれであり、文書化されていないものもありますので、それらをPHP実装の詳細として扱うことができます。
最初に、非通知メソッドで::
演算子を使用しないでください。これは、PHP通知では非推奨の動作です。
したがって、テストを2つの別々のテストに分割しましょう.1つは非静的メソッド用、もう1つは静的メソッド用です。ここ は非静的メソッドのテストです:
class ParentClass{
public function test($childObj){
$childObj->getProtected();
$childObj->getPrivate();
}
private function getPrivate(){
echo "ParentClass private";
}
protected function getProtected(){
echo "ParentClass protected";
}
}
class ChildClass extends ParentClass{
private function getPrivate(){
echo "ChildClass private";
}
protected function getProtected(){
echo "ChildClass protected";
}
}
(new ParentClass)->test(new ChildClass());
それは出力:
ChildClass protected
ParentClass private
そして、ここではphp documentationから関連する部分である:延期の場合
Objects of the same type will have access to each others private and protected members even though they are not the same instances. This is because the implementation specific details are already known when inside those objects.
、$childObj->getProtected();
- $childObj
はParentClass
のサブタイプであるため、同じタイプのオブジェクトとして扱うことができます。 は、そこでここでは、次のとおりです。
- は
getProtected()
方法
- このメソッドの呼び出し
ParentClass
タイプ
- のものとして
$childObj
変数の治療に保護されているので、継承ルールが適用され、私たちは、子クラスの実装を呼び出す
- "ChildClass protected"出力が得られます
私たちがpriで同じことをしようとするとvateメソッドでは、まだ$childObj->getPrivate()
を呼び出すことができますが、継承を介してプライベートメンバー/メソッドを使用することはできないため、継承ルールは適用されません。この時点で私たちは、次のとおりです。
- は、それがプライベートなので、継承ルールが適用されません
getPrivate()
メソッドを呼び出すParentClassタイプに
- であるとして
$childObj
変数を扱う(ただし、この言語の実装の詳細、下記参照)、我々は我々が静的メソッドメソッドたちのための「ParentClassプライベート」出力 今
を取得
ParentClassの実装を呼び出しますインスタンスレベルではなくクラスレベルのメソッドを呼び出すので、継承ルールはここでは適用できません。 私は、我々がこのよう静的呼び出しのためのコードを記述する場合は(私たちは本当にオブジェクトのインスタンスを必要としない、我々はクラス名のみを必要とする)明確だと思う:
class ParentClass{
public static function test() {
ChildClass::getProtected();
ChildClass::getPrivate();
}
}
class ChildClass extends ParentClass{
private static function getPrivate(){
echo "ChildClass private";
}
protected static function getProtected(){
echo "ChildClass protected";
}
}
(new ParentClass)->test();
それが出力されます。
ChildClass protected
PHP Fatal error: Uncaught Error: Call to private method ChildClass::getPrivate() from context 'ParentClass'
私は、2番目の呼び出しでエラーが発生するのは明らかです。別のクラスのprivate staicメソッドを呼び出そうとしています。
最初の呼び出しであるChildClass::getProtected()
が動作する理由はもっと面白いです。他のクラスの保護されたメソッドを呼び出そうとしており、継承ルールはここでは適用しないでください。
唯一の説明は、言語の実装の詳細です。 私はこの保護されたメソッド呼び出しは本当に動作しないはずだと思います。
私もここで私がthe first testのために得るものである、C++にこれを比較してみました:
#include <iostream>
using namespace std;
class ParentClass {
public:
void test(ParentClass* obj);
protected:
virtual void getProtected();
private:
virtual void getPrivate();
};
class ChildClass: public ParentClass{
protected:
virtual void getProtected();
private:
virtual void getPrivate();
};
//private virtual
void ParentClass::getPrivate(){
cout << "ParentClass private";
}
//protected virtual
void ParentClass::getProtected(){
cout << "ParentClass protected";
}
//public
void ParentClass::test(ParentClass* obj) {
obj->getProtected();
obj->getPrivate();
};
//private virtual
void ChildClass::getPrivate(){
cout << "ChildClass private";
}
//protected virtual
void ChildClass::getProtected(){
cout << "ChildClass protected";
}
int main() {
cout << "test";
(new ParentClass)->test(new ChildClass);
}
そして、それは出力:
test
ChildClass protected
ChildClass private
だから、違ったPHPでよりプライベートな方法のために働きますC++はprivateメソッドの場合でも実際に子クラスの実装を呼び出します。静的メソッドの
第二の試験は:
#include <iostream>
using namespace std;
class ParentClass {
public:
static void test();
};
class ChildClass: public ParentClass{
protected:
static void getProtected();
private:
static void getPrivate();
};
//public static
void ParentClass::test() {
// error: 'static void ChildClass::getProtected()' is protected
//ChildClass::getProtected();
// error: 'static void ChildClass::getPrivate()' is private
//ChildClass::getPrivate();
};
//private static
void ChildClass::getPrivate(){
cout << "ChildClass private";
}
//protected static
void ChildClass::getProtected(){
cout << "ChildClass protected";
}
int main() {
cout << "test";
(new ParentClass)->test();
}
どちらも保護され、民間の呼び出しは、ここでは動作しません。これらの呼び出しでは、プログラムをコンパイルすることすらできません。
これは、PHPで保護された静的メソッドを呼び出すことができるよりも論理的だと思います。
あるクラスインスタンスを使用して別のクラスインスタンスの値にアクセスして、意図的に継承を破ろうとしていますか?これは実際のコーディングではあまり現実的ではありません –
なぜスコープ解決 '::'演算子を持つクラスの非静的メソッドを呼び出すのですか? – Kamran
マーク・ベイカー、そうです、あなたが正しいと思います。私は実際に何をしようとしているのかわかりません、私はOOPについてのいくつかの本を読んでいました。そして、それは私のやり方です。私が何かを読んだとき、私はいつも自分に尋ねます。「もし私が好きなら、どうしたらいいでしょうか」:/ –