web-dev-qa-db-ja.com

パブリック、プライベート、プロテクトの違いは何ですか?

クラス内でpublicprivate、およびprotectedの各関数と変数を使用するのはいつどのような場合ですか?それらの違いは何ですか?

例:

// Public
public $variable;
public function doSomething() {
  // ...
}

// Private
private $variable;
private function doSomething() {
  // ...
}

// Protected
protected $variable;
protected function doSomething() {
  // ...
}
910
Adam

あなたが使う:

  • その変数/関数をどこからでも、他のクラスやオブジェクトのインスタンスからも利用できるようにするpublicスコープ。

  • あなたの変数/関数をそれ自身のクラスでのみ見えるようにしたい場合はprivateスコープ。

  • 親クラスを含め、現在のクラスを拡張するすべてのクラスで変数/関数を見えるようにしたい場合はprotectedスコープ。

その他: (総合情報)

1188
Sarfraz

dd

パブリック:

メソッド(関数)またはプロパティ(変数)を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にアクセスできません


Reflection を使用したおじいちゃんクラスの分析

このテーマは実際には範囲外ではありません。ここでは、リフレクションが本当に強力であることを証明するためにここに追加します。上記の3つの例で述べたように、protectedおよびprivateメンバー(プロパティとメソッド)はクラスの外部からアクセスできません。

ただし、リフレクションを使用すると、protectedおよびにアクセスすることでも、extra-ordinaryを実行できます。/privateクラス外のメンバー!

さて、反射とは何ですか?

Reflectionは、クラス、インターフェイス、関数、メソッド、および拡張機能をリバースエンジニアリングする機能を追加します。さらに、関数、クラス、およびメソッドのドキュメントコメントを取得する方法も提供します。

前文

Grandpasという名前のクラスがあり、3つのプロパティがあるとします。わかりやすくするために、名前の付いたおじいちゃんが3人いるとします。

  • マーク・ヘンリー
  • ジョン・クラッシュ
  • ウィル・ジョーンズ

それらを(変数を割り当てて)それぞれpublicprotectedprivateとします。 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_rvar_export、およびvar_dumpは、 デバッガー関数 です。それらは、人間が読める形式で変数に関する情報を提示します。これらの3つの関数は、PHP 5を持つオブジェクトのprotectedおよびprivateプロパティを明らかにします。静的クラスメンバーはnotが表示されます。


その他のリソース:


1132

これは、データのカプセル化と優れたインターフェース設計を促進するため、デフォルトで必要最低限​​の可視性にデフォルト設定することをお勧めします。メンバー変数とメソッドの可視性を検討する際には、メンバーが他のオブジェクトとの対話で果たす役割について考えてください。

あなたが「実装ではなくインターフェースにコードを書く」なら、可視性の決定をするのは通常とても簡単です。一般に、変数を公開する十分な理由がない限り、変数は非公開または保護されている必要があります。クラスの内部へのアクセスを制限および規制するには、代わりにパブリックアクセサ(ゲッター/セッター)を使用してください。

例えとして自動車を使用するには、速度、ギア、方向などがプライベートインスタンス変数になります。運転者に空燃比のようなものを直接操作させたくはありません。代わりに、あなたはパブリックメソッドとして限られた数のアクションを公開します。自動車へのインターフェースには、accelerate()deccelerate()/brake()setGear()turnLeft()turnRight()などのメソッドが含まれます。

運転手は、これらの動作が車の内部構造によってどのように実行されるのかを知らず、また気にすべきではありません。したがって、パブリックインタフェースを設計し、そのインタフェースの背後にあるデータをカプセル化することをお勧めします。

この方法では、インターフェイスとクライアントコードとの契約を破ることなく、クラス内のパブリックメソッドの実装を変更および改善することもできます。たとえば、accelerate()メソッドをさらに燃費効率の良いものにすることができますが、そのメソッドの使用法は変わりません。クライアントコードを変更する必要はありませんが、それでも効率が向上するという利点があります。

編集:オブジェクト指向の概念(どの言語の構文よりも習得するのがはるかに難しい)をまだ学習中であるように思われるので、I 非常に PHPオブジェクト、パターン、そして実践 Matt Zandstra著。これは最初に how がOOPを効果的に使うことを私に教えただけの本です。私は何年も前からその構文を学んでいましたが、それはOOPの「なぜ」を理解しなければ役に立ちませんでした。

82
The Awnry Bear

private - WITHINクラスからのみアクセス可能

protected - クラス内およびクラスINHERITINGからアクセスできます。

public - クラス外のコードからもアクセス可能

これは変数だけでなく関数にも適用されます。

74
Olaf

違いは次のとおりです。

Public::パブリック変数またはメソッドは、そのクラスのすべてのユーザーが直接アクセスできます。

Protected::保護された変数またはメソッドは、そのクラスのユーザーからはアクセスできませんが、そのクラスから継承したサブクラスの内部ではアクセスできます。

Private::プライベート変数またはメソッドは、それが定義されているクラスから内部的にのみアクセスできます。つまり、プライベート変数またはメソッドは、クラスを拡張する子から呼び出すことはできません。

25
Matthew Watts

可視性の範囲 with 抽象的な例 :: 理解を容易にする

このプロパティまたはメソッドの可視性は、3つのキーワード(Public、protected、およびprivate)のうちの1つの宣言を事前に固定することによって定義されます。

Public :プロパティまたはメソッドがパブリックとして定義されている場合、それはオブジェクトを参照できるものであればアクセスと操作の両方が可能であることを意味します。

  • 抽象的です。公衆の視界の範囲を "public picnic" だれでもとれると考えてください。

保護された: プロパティまたはメソッドの可視性が保護されたメンバに設定されている場合は、クラス自体の中、および継承したクラスと継承したクラスによってのみアクセスできます。 (継承: - クラスは他のクラスのすべてのプロパティとメソッドを持つことができます)。

  • 保護された可視範囲として "会社のピクニック" 会社のメンバーとその家族が一般には許可されていない場所として考えてください。これは最も一般的なスコープ制限です。

非公開: プロパティまたはメソッドの表示設定が非公開に設定されている場合、クラスの関係にかかわらず、非公開のメンバを持つクラスのみがそれらのメソッドおよびプロパティにアクセスできます(クラス内)。

  • ピクニックアナロジーで "会社のメンバーだけが許可されている会社のピクニック"と考える /ピクニックで。家族でも一般市民でも許可されていません。
16
Suman K.C
/**
 * 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

から抽出:

http://php.net/manual/en/language.oop5.visibility.php

14
Techie

これはpublicprotectedprivateの範囲を覚える簡単な方法です。

PUBLIC

  • publicスコープ:パブリック変数/関数はオブジェクトと他のクラスの両方に利用可能です。

PROTECTED

  • protectedスコープ:現在のクラスを拡張するすべてのクラスで保護された変数/関数が利用可能です。
  • いいえ!オブジェクトはこのスコープにアクセスできません

PRIVATE

  • privateスコープ:プライベート変数/関数は、それが定義されている現在のクラスでのみ表示されます。
  • いいえ!現在のクラスを拡張するクラスはこのスコープにアクセスできません。
  • いいえ!オブジェクトはこのスコープにアクセスできません。

PHP Manualにあるメソッドまたは変数の 可視性 を読みます。

11
Ahmad Awais

' when 'を考えると:
よくわからない場合は、最初はすべて非公開として宣言します。その理由は、プライベートメソッドを公開する方が他の方法よりもはるかに簡単だからです。これは、プライベートメソッドがクラス内以外では使用されていないことを少なくとも確信できるからです。公開メソッドはすでに至る所で使用されている可能性があり、おそらく大規模な書き換えが必要になります。

Update :私は最近protectedのデフォルトを使います。カプセル化には十分で、クラスを拡張するときに邪魔にならないことに気付いたからです。 。私が他の2つを使うもっともな理由があるならば、私はそうするでしょう。

privateメソッドの正当な理由は、そのオブジェクトに固有のもので、拡張クラスでさえも変更すべきでないものを実装していることです(内部状態管理のようなカプセル化に加えて、実際の理由)。結局、protectedメソッドが通常どこで使用されているのかを追跡するのはまだ十分に簡単なので、最近はprotectedをデフォルトにします。たぶん100%の客観的な「塹壕の中で」の経験ではない、と私は認める。

8
DanMan

私にとって、これは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();
6
Andrew

PHPマニュアルは質問 here についてよく読んでいます。

プロパティまたはメソッドの可視性は、宣言の前にキーワードpublic、protected、またはprivateを付けることによって定義できます。 publicと宣言されたクラスメンバーはどこからでもアクセスできます。 protectedと宣言されたメンバは、クラス自体の中で、そして継承クラスと親クラスによってのみアクセスできます。非公開として宣言されたメンバーは、そのメンバーを定義するクラスによってのみアクセスされます。

6
code_burgar

PHPの変数は3つの異なる型にキャストされます。

パブリック:この変数型の値はすべてのスコープで利用可能であり、あなたのコードの実行を要求します。 public $examTimeTable;として宣言してください

非公開:このタイプの変数の値は、それが属するクラスでのみ利用可能です。 private $classRoomComputers;

Protected:このクラスの値は、Accessが継承の形で与えられたとき、またはその子クラスのときにのみ利用可能です。一般的には::を使用して親クラスによるアクセスを許可しました

protected $familyWealth;

4
star18bit

さまざまなレベルの カプセル化 を考慮しています。

4
Mchl

古い質問を復活させますが、これを考えるための本当に良い方法はあなたが定義しているAPIの観点からです。

  • public - publicとマークされたものはすべて、あなたのクラス/インタフェース/その他を使っている人が誰でも使用し、信頼するAPIの一部です。

  • protected - だまされてはいけません。これもAPIの一部です!人々はサブクラス化してあなたのコードを拡張しそして保護されたとマークされたものを使うことができます。

  • private - プライベートなプロパティやメソッドは自由に変更することができます。誰もこれらを使用することはできません。これらはあなたが大きな変更を加えることなく変更できる唯一のものです。

または Semver の場合:

  • publicまたはprotectedへの変更は、メジャー変更と見なされるべきです。

  • 新しいpublicまたはprotectedは(少なくとも)MINORであるべきです

  • privateへの新規追加/変更のみがPATCHになります

それで、コードを維持することに関して、あなたが何をpublicまたはprotectedにするかについて注意することは良いことです。

3
mcfedr

私たちのプロジェクトでオブジェクト指向のphpに従うとき、私たちはphpでアクセス修飾子を使うためにいくつかの規則に従うべきです。今日、私たちはアクセス修飾子とは何か、そしてそれをどのように使うことができるかをはっきりと学びます。PHPアクセス修飾子はPHPクラスとそのメンバーでアクセス権を設定するために使われます。 phpではクラスメンバーには3つのスコープがあります。

  1. パブリック
  2. プライベート
  3. 保護されています

今、私たちはアクセス修飾子のアクセスレベルを理解するために次の画像を見てみましょう enter image description here

それでは、アクセス修飾子として使用される可能性のあるPHPキーワードについて知るために、以下のリストを見てみましょう。

public: - このアクセス修飾子で定義されたクラスまたはそのメンバは、クラスの範囲外であっても、どこからでもパブリックにアクセス可能になります。

private: - このキーワードを持つクラスメンバーはクラス自身の中でアクセスされます。サブクラスからプライベートデータにアクセスすることはできません。メンバーを外部からのアクセスから保護します。

protected: - サブクラスから保護されたスーパークラスメンバーへのアクセスを許可すること以外はprivateと同じです。

今すぐアクセス修飾子を理解するためにテーブルを参照してください。記事全文を読む phpアクセス修飾子

1

Public:変数やメソッドを宣言したときのデフォルトの状態です。オブジェクトに直接アクセスすることで、誰でもアクセスできます。

Protected:オブジェクトとサブクラス内でのみアクセスできます。

Private:サブクラスではなく、オブジェクト内でのみ参照できます。

1
Nomadme