クラス内でpublic
、private
、およびprotected
の各関数と変数を使用するのはいつどのような場合ですか?それらの違いは何ですか?
例:
// Public
public $variable;
public function doSomething() {
// ...
}
// Private
private $variable;
private function doSomething() {
// ...
}
// Protected
protected $variable;
protected function doSomething() {
// ...
}
あなたが使う:
その変数/関数をどこからでも、他のクラスやオブジェクトのインスタンスからも利用できるようにするpublic
スコープ。
あなたの変数/関数をそれ自身のクラスでのみ見えるようにしたい場合はprivate
スコープ。
親クラスを含め、現在のクラスを拡張するすべてのクラスで変数/関数を見えるようにしたい場合はprotected
スコープ。
その他: (総合情報)
メソッド(関数)またはプロパティ(変数)をpublic
として宣言すると、それらのメソッドとプロパティには次の方法でアクセスできます。
例:
<?php
class GrandPa
{
public $name='Mark Henry'; // A public variable
}
class Daddy extends GrandPa // Inherited class
{
function displayGrandPaName()
{
return $this->name; // The public variable will be available to the inherited class
}
}
// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
メソッド(関数)またはプロパティ(変数)をprotected
として宣言すると、それらのメソッドとプロパティにアクセスできます
部外者はこれらの変数にアクセスできません。宣言されたクラス自体のobjectインスタンスではないという意味での「外部者」。
例:
<?php
class GrandPa
{
protected $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
正確なエラーは次のとおりです。
PHP致命的エラー:保護されたプロパティGrandPa :: $ nameにアクセスできません
メソッド(関数)またはプロパティ(変数)をprivate
として宣言すると、それらのメソッドとプロパティには次の方法でアクセスできます。
部外者はこれらの変数にアクセスできません。宣言されたクラス自体のオブジェクトインスタンスではなく、宣言されたクラスを継承するクラスでさえないという意味での部外者。
例:
<?php
class GrandPa
{
private $name = 'Mark Henry';
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
正確なエラーメッセージは次のとおりです。
Notice:未定義のプロパティ:Daddy :: $ name
致命的なエラー:プライベートプロパティGrandPa :: $ nameにアクセスできません
このテーマは実際には範囲外ではありません。ここでは、リフレクションが本当に強力であることを証明するためにここに追加します。上記の3つの例で述べたように、protected
およびprivate
メンバー(プロパティとメソッド)はクラスの外部からアクセスできません。
ただし、リフレクションを使用すると、protected
およびにアクセスすることでも、extra-ordinaryを実行できます。/private
クラス外のメンバー!
Reflectionは、クラス、インターフェイス、関数、メソッド、および拡張機能をリバースエンジニアリングする機能を追加します。さらに、関数、クラス、およびメソッドのドキュメントコメントを取得する方法も提供します。
Grandpas
という名前のクラスがあり、3つのプロパティがあるとします。わかりやすくするために、名前の付いたおじいちゃんが3人いるとします。
それらを(変数を割り当てて)それぞれpublic
、protected
、private
とします。 protected
およびprivate
メンバーはクラスの外部からアクセスできないことをよく知っています。次に、リフレクションを使用してステートメントを矛盾させましょう。
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;
# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
echo "<br>";
#Scenario 2: Using reflection
$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)
echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";
foreach($granpaNames as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
出力:
#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1
#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3
以下の例と混同しないでください。ご覧のとおり、private
およびprotected
メンバーには、リフレクションを使用せずにクラスのoutsideにアクセスできません
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);
出力:
GrandPas Object
(
[name1] => Mark Henry
[name2:protected] => John Clash
[name3:GrandPas:private] => Will Jones
)
print_r
、var_export
、およびvar_dump
は、 デバッガー関数 です。それらは、人間が読める形式で変数に関する情報を提示します。これらの3つの関数は、PHP 5を持つオブジェクトのprotected
およびprivate
プロパティを明らかにします。静的クラスメンバーはnotが表示されます。
これは、データのカプセル化と優れたインターフェース設計を促進するため、デフォルトで必要最低限の可視性にデフォルト設定することをお勧めします。メンバー変数とメソッドの可視性を検討する際には、メンバーが他のオブジェクトとの対話で果たす役割について考えてください。
あなたが「実装ではなくインターフェースにコードを書く」なら、可視性の決定をするのは通常とても簡単です。一般に、変数を公開する十分な理由がない限り、変数は非公開または保護されている必要があります。クラスの内部へのアクセスを制限および規制するには、代わりにパブリックアクセサ(ゲッター/セッター)を使用してください。
例えとして自動車を使用するには、速度、ギア、方向などがプライベートインスタンス変数になります。運転者に空燃比のようなものを直接操作させたくはありません。代わりに、あなたはパブリックメソッドとして限られた数のアクションを公開します。自動車へのインターフェースには、accelerate()
、deccelerate()
/brake()
、setGear()
、turnLeft()
、turnRight()
などのメソッドが含まれます。
運転手は、これらの動作が車の内部構造によってどのように実行されるのかを知らず、また気にすべきではありません。したがって、パブリックインタフェースを設計し、そのインタフェースの背後にあるデータをカプセル化することをお勧めします。
この方法では、インターフェイスとクライアントコードとの契約を破ることなく、クラス内のパブリックメソッドの実装を変更および改善することもできます。たとえば、accelerate()
メソッドをさらに燃費効率の良いものにすることができますが、そのメソッドの使用法は変わりません。クライアントコードを変更する必要はありませんが、それでも効率が向上するという利点があります。
編集:オブジェクト指向の概念(どの言語の構文よりも習得するのがはるかに難しい)をまだ学習中であるように思われるので、I 非常に PHPオブジェクト、パターン、そして実践 Matt Zandstra著。これは最初に how がOOPを効果的に使うことを私に教えただけの本です。私は何年も前からその構文を学んでいましたが、それはOOPの「なぜ」を理解しなければ役に立ちませんでした。
private
- WITHINクラスからのみアクセス可能
protected
- クラス内およびクラスINHERITINGからアクセスできます。
public
- クラス外のコードからもアクセス可能
これは変数だけでなく関数にも適用されます。
違いは次のとおりです。
Public
::パブリック変数またはメソッドは、そのクラスのすべてのユーザーが直接アクセスできます。
Protected
::保護された変数またはメソッドは、そのクラスのユーザーからはアクセスできませんが、そのクラスから継承したサブクラスの内部ではアクセスできます。
Private
::プライベート変数またはメソッドは、それが定義されているクラスから内部的にのみアクセスできます。つまり、プライベート変数またはメソッドは、クラスを拡張する子から呼び出すことはできません。
可視性の範囲 with 抽象的な例 :: 理解を容易にする
このプロパティまたはメソッドの可視性は、3つのキーワード(Public、protected、およびprivate)のうちの1つの宣言を事前に固定することによって定義されます。
Public :プロパティまたはメソッドがパブリックとして定義されている場合、それはオブジェクトを参照できるものであればアクセスと操作の両方が可能であることを意味します。
保護された: プロパティまたはメソッドの可視性が保護されたメンバに設定されている場合は、クラス自体の中、および継承したクラスと継承したクラスによってのみアクセスできます。 (継承: - クラスは他のクラスのすべてのプロパティとメソッドを持つことができます)。
非公開: プロパティまたはメソッドの表示設定が非公開に設定されている場合、クラスの関係にかかわらず、非公開のメンバを持つクラスのみがそれらのメソッドおよびプロパティにアクセスできます(クラス内)。
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
これは
public
、protected
、private
の範囲を覚える簡単な方法です。
PUBLIC
:
public
スコープ:パブリック変数/関数はオブジェクトと他のクラスの両方に利用可能です。PROTECTED
:
protected
スコープ:現在のクラスを拡張するすべてのクラスで保護された変数/関数が利用可能です。PRIVATE
:
private
スコープ:プライベート変数/関数は、それが定義されている現在のクラスでのみ表示されます。PHP Manualにあるメソッドまたは変数の 可視性 を読みます。
' when 'を考えると:
よくわからない場合は、最初はすべて非公開として宣言します。その理由は、プライベートメソッドを公開する方が他の方法よりもはるかに簡単だからです。これは、プライベートメソッドがクラス内以外では使用されていないことを少なくとも確信できるからです。公開メソッドはすでに至る所で使用されている可能性があり、おそらく大規模な書き換えが必要になります。
Update :私は最近protected
のデフォルトを使います。カプセル化には十分で、クラスを拡張するときに邪魔にならないことに気付いたからです。 。私が他の2つを使うもっともな理由があるならば、私はそうするでしょう。
private
メソッドの正当な理由は、そのオブジェクトに固有のもので、拡張クラスでさえも変更すべきでないものを実装していることです(内部状態管理のようなカプセル化に加えて、実際の理由)。結局、protected
メソッドが通常どこで使用されているのかを追跡するのはまだ十分に簡単なので、最近はprotected
をデフォルトにします。たぶん100%の客観的な「塹壕の中で」の経験ではない、と私は認める。
私にとって、これは3つのプロパティタイプを理解するのに最も有用な方法です:
パブリック:コード内のどこからでもこの変数に直接アクセスして変更できる状態で問題ない場合に使用します。
クラス外からの使用例:
$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;
Protected:変数にアクセスして設定するときに、クラス外で他のプログラマー(および自分)にゲッター/セッターを使用するように強制する場合に使用します(ただし、一貫性を保ち、内部でゲッターとセッターを使用する必要があります)クラスも)。これまたはprivate
は、すべてのクラスプロパティを設定するデフォルトの方法である傾向があります。
どうして?将来のある時点(おそらく5分程度)で、そのプロパティに対して返される値を操作したり、取得/設定する前に何かを行うことを決定した場合、どこでもリファクタリングせずにそれを行うことができるためプロジェクトで使用しました。
クラス外からの使用例:
$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();
プライベート:private
プロパティはprotected
プロパティに非常に似ています。ただし、特徴的な違いは、private
にすると、親クラスのgetterまたはsetterを使用せずに子クラスにアクセスできなくなることです。
したがって、基本的に、プロパティにゲッターとセッターを使用している場合(または親クラスによって内部でのみ使用され、他のどこからもアクセスできないようにする場合)、同様にprivate
にすることもできます誰もが直接それを使用しようとするのを防ぎ、バグを導入する。
(MyObjectを拡張する)子クラス内の使用例:
$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
PHPマニュアルは質問 here についてよく読んでいます。
プロパティまたはメソッドの可視性は、宣言の前にキーワードpublic、protected、またはprivateを付けることによって定義できます。 publicと宣言されたクラスメンバーはどこからでもアクセスできます。 protectedと宣言されたメンバは、クラス自体の中で、そして継承クラスと親クラスによってのみアクセスできます。非公開として宣言されたメンバーは、そのメンバーを定義するクラスによってのみアクセスされます。
PHPの変数は3つの異なる型にキャストされます。
パブリック:この変数型の値はすべてのスコープで利用可能であり、あなたのコードの実行を要求します。 public $examTimeTable;
として宣言してください
非公開:このタイプの変数の値は、それが属するクラスでのみ利用可能です。 private $classRoomComputers;
Protected:このクラスの値は、Accessが継承の形で与えられたとき、またはその子クラスのときにのみ利用可能です。一般的には::
を使用して親クラスによるアクセスを許可しました
protected $familyWealth;
さまざまなレベルの カプセル化 を考慮しています。
古い質問を復活させますが、これを考えるための本当に良い方法はあなたが定義しているAPIの観点からです。
public
- publicとマークされたものはすべて、あなたのクラス/インタフェース/その他を使っている人が誰でも使用し、信頼するAPIの一部です。
protected
- だまされてはいけません。これもAPIの一部です!人々はサブクラス化してあなたのコードを拡張しそして保護されたとマークされたものを使うことができます。
private
- プライベートなプロパティやメソッドは自由に変更することができます。誰もこれらを使用することはできません。これらはあなたが大きな変更を加えることなく変更できる唯一のものです。
または Semver の場合:
public
またはprotected
への変更は、メジャー変更と見なされるべきです。
新しいpublic
またはprotected
は(少なくとも)MINORであるべきです
private
への新規追加/変更のみがPATCHになります
それで、コードを維持することに関して、あなたが何をpublic
またはprotected
にするかについて注意することは良いことです。
私たちのプロジェクトでオブジェクト指向のphpに従うとき、私たちはphpでアクセス修飾子を使うためにいくつかの規則に従うべきです。今日、私たちはアクセス修飾子とは何か、そしてそれをどのように使うことができるかをはっきりと学びます。PHPアクセス修飾子はPHPクラスとそのメンバーでアクセス権を設定するために使われます。 phpではクラスメンバーには3つのスコープがあります。
今、私たちはアクセス修飾子のアクセスレベルを理解するために次の画像を見てみましょう
それでは、アクセス修飾子として使用される可能性のあるPHPキーワードについて知るために、以下のリストを見てみましょう。
public: - このアクセス修飾子で定義されたクラスまたはそのメンバは、クラスの範囲外であっても、どこからでもパブリックにアクセス可能になります。
private: - このキーワードを持つクラスメンバーはクラス自身の中でアクセスされます。サブクラスからプライベートデータにアクセスすることはできません。メンバーを外部からのアクセスから保護します。
protected: - サブクラスから保護されたスーパークラスメンバーへのアクセスを許可すること以外はprivateと同じです。
今すぐアクセス修飾子を理解するためにテーブルを参照してください。記事全文を読む phpアクセス修飾子
Public
:変数やメソッドを宣言したときのデフォルトの状態です。オブジェクトに直接アクセスすることで、誰でもアクセスできます。
Protected
:オブジェクトとサブクラス内でのみアクセスできます。
Private
:サブクラスではなく、オブジェクト内でのみ参照できます。