web-dev-qa-db-fra.com

Quelle est la différence entre public, privé et protégé?

Quand et pourquoi devrais-je utiliser des fonctions et des variables public, private et protected dans une classe? Quelle est la différence entre eux?

Exemples:

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

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

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

Tu utilises:

  • public portée pour rendre cette variable/fonction disponible à partir de n’importe où, des autres classes et instances de l’objet.

  • private scope lorsque vous souhaitez que votre variable/fonction soit visible uniquement dans sa propre classe.

  • protected scope lorsque vous souhaitez rendre votre variable/fonction visible dans toutes les classes qui étendent la classe actuelle, y compris la classe parente.

More: (Pour une information complète)

1162
Sarfraz

dd

Publique:

Lorsque vous déclarez une méthode (fonction) ou une propriété (variable) en tant que public, vous pouvez accéder à ces méthodes et propriétés de la manière suivante:

  • La même classe qui l'a déclaré.
  • Les classes qui héritent de la classe déclarée ci-dessus.
  • Tous les éléments étrangers en dehors de cette classe peuvent également accéder à ces éléments.

Exemple:

<?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'

Protégé:

Lorsque vous déclarez une méthode (fonction) ou une propriété (variable) en tant que protected, vous pouvez accéder à ces méthodes et propriétés en

  • La même classe qui l'a déclaré.
  • Les classes qui héritent de la classe déclarée ci-dessus.

Les membres externes ne peuvent pas accéder à ces variables. "Outsiders" en ce sens qu'ils ne sont pas des instances object de la classe déclarée elle-même.

Exemple:

<?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

L'erreur exacte sera la suivante:

Erreur irrécupérable PHP: impossible d'accéder à la propriété protégée GrandPa :: $ name


Privé:

Lorsque vous déclarez une méthode (fonction) ou une propriété (variable) en tant que private, vous pouvez accéder à ces méthodes et propriétés de la manière suivante:

  • La même classe qui l'a déclaré.

Les membres externes ne peuvent pas accéder à ces variables. Les personnes extérieures au sens où elles ne sont pas des instances object de la classe déclarée elle-même et même des classes qui héritent de la classe déclarée.

Exemple:

<?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

Les messages d'erreur exacts seront:

Avis: Propriété non définie: Daddy :: $ name
Erreur fatale: impossible d'accéder à la propriété privée GrandPa :: $ name


Dissection de la classe de papy avec Reflection

Ce sujet n’est pas vraiment hors de propos, et je l’ajoute ici juste pour prouver que la réflexion est vraiment puissante. Comme je l'ai indiqué dans les trois exemples ci-dessus, les membres protected et private (propriétés et méthodes) ne sont pas accessibles en dehors de la classe. 

Cependant, avec réflexion, vous pouvez faire les extraordinaires en accédant même aux membres protected et private en dehors de la classe!

Eh bien, qu'est-ce que la réflexion?

Reflection ajoute la possibilité de désosser des classes, des interfaces, fonctions, méthodes et extensions. En outre, ils offrent des moyens de récupère les commentaires de doc pour les fonctions, les classes et les méthodes.

Préambule

Nous avons une classe nommée Grandpas et disons que nous avons trois propriétés. Pour faciliter la compréhension, considérez qu'il y a trois grands-pères portant des noms:

  • Marc Henry
  • John Clash
  • Will Jones

Faisons-leur (assigner des modificateurs) public, protected et private respectivement. Vous savez très bien que les membres protected et private ne sont pas accessibles en dehors de la classe. Maintenant, contredisons la déclaration en utilisant la réflexion.

Le code

<?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>";
}

Sortie:

#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

Erreur commune:

S'il vous plaît ne confondez pas avec l'exemple ci-dessous. Comme vous pouvez toujours le constater, les membres private et protected ne sont pas accessibles en dehors de de la classe sans utiliser la réflexion.

<?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);

Sortie:

GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John Clash
    [name3:GrandPas:private] => Will Jones
)

Fonctions de débogage

print_r, var_export et var_dump sont fonctions de débogage . Ils présentent des informations sur une variable sous une forme lisible par l'homme. Ces trois fonctions révéleront les propriétés protected et private des objets avec PHP 5. Les membres statiques de la classe seront non affichés.


Plus de ressources:


1083
Shankar Damodaran

Il est généralement considéré comme une bonne pratique de choisir la visibilité la plus faible requise par défaut, car cela favorise l'encapsulation des données et une bonne conception de l'interface. Lorsque vous considérez la visibilité de la variable et de la méthode du membre, réfléchissez au rôle que le membre joue dans l'interaction avec d'autres objets.

Si vous "codez pour une interface plutôt que pour une implémentation", il est généralement assez simple de prendre des décisions de visibilité. En général, les variables doivent être privées ou protégées sauf si vous avez une bonne raison de les exposer. Utilisez plutôt des accesseurs publics (getters/setters) pour limiter et réglementer l'accès aux composants internes d'une classe.

Pour utiliser une voiture comme analogie, des éléments tels que la vitesse, la vitesse et la direction seraient des variables d'instance privées. Vous ne voulez pas que le conducteur manipule directement des choses comme le rapport air/carburant. Au lieu de cela, vous exposez un nombre limité d'actions en tant que méthodes publiques. L'interface vers une voiture peut inclure des méthodes telles que accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), etc.

Le conducteur ne sait pas et ne doit pas se soucier de savoir comment ces actions sont mises en œuvre par les internes de la voiture, et exposer cette fonctionnalité pourrait être dangereux pour le conducteur et les autres sur la route. D'où la bonne pratique de concevoir une interface publique et d'encapsuler les données derrière cette interface.

Cette approche vous permet également de modifier et d'améliorer l'implémentation des méthodes publiques dans votre classe sans rompre le contrat de l'interface avec le code client. Par exemple, vous pourriez améliorer la méthode accelerate() pour qu'elle consomme moins de carburant, mais son utilisation resterait la même; Le code client ne nécessiterait aucun changement, mais tirerait tout de même les avantages de votre amélioration de l'efficacité.

Edit: Puisqu'il semble que vous êtes encore en train d'apprendre des concepts orientés objet (qui sont beaucoup plus difficiles à maîtriser que la syntaxe de n'importe quelle langue), je vivement recommande de prendre un exemplaire de PHP Objets, motifs et pratique par Matt Zandstra. C’est le livre qui m’a appris pour la première fois à comment à utiliser OOP de manière efficace, plutôt que de simplement m'apprendre la syntaxe. J'avais appris la syntaxe des années auparavant, mais c'était inutile sans comprendre le "pourquoi" de la POO.

82
The Awnry Bear

private - accessible depuis DANS la classe uniquement

protected - peut être accédé depuis les classes WITHIN et INHERITING

public - peut également être consulté à partir du code extérieur de la classe

Ceci s’applique tant aux fonctions qu’aux variables.

73
Olaf

La différence est la suivante:

Public:: Une variable ou une méthode publique est directement accessible à tout utilisateur de la classe.

Protected:: Une variable ou une méthode protégée n'est pas accessible aux utilisateurs de la classe, mais à l'intérieur d'une sous-classe qui hérite de la classe.

Private:: Une variable ou méthode privée est accessible uniquement de manière interne depuis la classe dans laquelle elle est définie. Cela signifie qu'une variable ou méthode privée ne peut pas être appelée depuis un enfant qui étend la classe.

25
Matthew Watts

Visibilité avec Exemples de résumé :: facilite la compréhension

Cette visibilité d'une propriété ou d'une méthode est définie par la déclaration préalable d'un des trois mots clés (Public, protected et private).

Public : Si une propriété ou une méthode est définie comme publique, cela signifie qu'elle peut être à la fois accessible et manipulée par tout ce qui peut faire référence à object.

  • Résumé par exemple. Pensez à la portée de la visibilité publique comme "pique-nique public" que n'importe qui peut venir.

Protégé: lorsqu'une propriété ou une méthode a la visibilité sur des membres protégés, l'accès ne peut être accessible qu'à l'intérieur de la classe et par les classes héritées et héritées. (Hérité: - une classe peut avoir toutes les propriétés et les méthodes d'une autre classe).

  • Pensez comme un champ de visibilité protégé comme "Pique-nique d'entreprise" où les membres de l'entreprise et les membres de leur famille sont autorisés, pas le public. C'est la restriction la plus courante.

Private: Quand la visibilité d'une propriété ou d'une méthode est définie sur private, seule la classe possédant les membres privés peut accéder à ces méthodes et propriétés (en interne dans la classe), quelle que soit la relation de classe qui existe.

  • avec l'analogie du pique-nique, pensez comme un "pique-nique d'entreprise où seuls les membres de l'entreprise sont autorisés" dans le pique-nique. pas la famille ni le grand public sont autorisés.
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

Extrait de :

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

14
Techie

Voici un moyen facile de mémoriser la portée de public, protected et private.

PUBLIC:

  • public scope: Une variable/fonction publique est disponible pour les objets et les autres classes.

PROTECTED:

  • protected scope: Une variable/fonction protégée est disponible pour toutes les classes qui étendent la classe actuelle. 
  • Non! Les objets ne peuvent pas accéder à cette étendue

PRIVATE:

  • private scope: Une variable/fonction privée n'est visible que dans la classe en cours où elle est définie.
  • Non! Les classes qui étendent la classe actuelle ne peuvent pas accéder à cette étendue.
  • Non! Les objets ne peuvent pas accéder à cette étendue.

Lisez le Visibility d'une méthode ou d'une variable dans le manuel PHP.

11
Ahmad Awais

Considérant 'when':
Au début, j'ai tendance à tout déclarer privé, si je ne suis pas tout à fait sûr. Raison d'être, il est généralement beaucoup plus facile de rendre publique une méthode privée que l'inverse. C'est parce que vous pouvez au moins être sûr que la méthode privée n'a été utilisée nulle part ailleurs que dans la classe elle-même. Une méthode publique peut déjà être utilisée partout, nécessitant éventuellement une réécriture étendue.

Mise à jour : Je pars pour un défaut de protected de nos jours, car j’ai découvert que c’est suffisant pour l’encapsulation et qui ne gêne pas lorsque j’étends des classes (que j’essaie d’éviter de toute façon) . Seulement si j'ai une bonne raison d'utiliser les deux autres, je le ferai.

Une bonne méthode pour une méthode private serait une méthode qui implémenterait quelque chose d'inhérent à cet objet que même une classe étendue ne devrait pas changer (raison factuelle, en plus de l'encapsulation, comme la gestion interne de l'état). En fin de compte, il est toujours assez facile de déterminer où une méthode protected est habituellement utilisée, aussi, la valeur par défaut est protected de nos jours. Peut-être pas une expérience 100% objective "dans les tranchées", je l'avoue.

8
DanMan

Pour moi, c’est le plus utile moyen de comprendre les trois types de propriétés:

Public : Utilisez ceci quand vous êtes d'accord avec cette variable étant directement accédée et modifiée de n'importe où dans votre code. 

Exemple d'utilisation en dehors de la classe:

$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;

Protected : Utilisez-le lorsque vous voulez obliger les autres programmeurs (et vous-même) à utiliser des accesseurs/séparateurs en dehors de la classe lors de l'accès aux variables et de leur définition (vous devez cependant être cohérent et utiliser les accesseurs et les configurateurs de la classe ). Ce nom ou private est généralement le moyen par défaut de configurer toutes les propriétés de classe. 

Pourquoi? Parce que si vous décidez ultérieurement (peut-être même dans environ 5 minutes) de manipuler la valeur renvoyée pour cette propriété ou de faire quelque chose avec elle avant d'obtenir/de définir, vous pouvez le faire sans refactoring où que vous soyez. utilisé dans votre projet.

Exemple d'utilisation en dehors de la classe:

$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();

Private : Les propriétés private sont très similaires aux propriétés protected. Mais la particularité/différence est que rendre private le rend également inaccessible aux classes enfants sans utiliser le getter ou le setter de la classe parent. 

Donc, si vous utilisez des getters et des setters pour une propriété (ou si elle est utilisée uniquement en interne par la classe parente et qu'elle n'est censée être accessible nulle part ailleurs), vous pouvez tout aussi bien en faire private, simplement pour empêcher quiconque en essayant de l'utiliser directement et introduisant des bugs.

Exemple d'utilisation dans une classe enfant (qui étend MyObject):

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();
6
Andrew

Le manuel PHP a une bonne lecture sur la question ici

La visibilité d'une propriété ou d'une méthode peut être définie en préfixant la déclaration avec les mots-clés public, protected ou private. Les membres de classe déclarés publics sont accessibles partout. Les membres déclarés protégés ne sont accessibles qu'au sein de la classe et par les classes héritées et parent. Les membres déclarés comme privés ne peuvent être consultés que par la classe qui définit le membre. 

6
code_burgar

Les variables entre PHP sont exprimées en trois types différents:

Public: les valeurs de cette variable sont disponibles dans toutes les portées et appellent lors de l'exécution de votre code ..__ déclare en tant que: public $examTimeTable;

Private: les valeurs de ce type de variable ne sont disponibles que sur la classe à laquelle il appartient . private $classRoomComputers;

Protected: Valeurs de cette classe uniquement et disponibles uniquement lorsque Access a été accordé sous forme d'héritage ou de sa classe enfant. généralement utilisé :: pour accorder l'accès par classe parent

protected $familyWealth;

4
star18bit

Ils sont là pour permettre différents niveaux de encapsulation

4
Mchl

Je reviens à une vieille question, mais je pense que l’API que vous définissez est un très bon moyen d’y réfléchir.

  • public - Tout ce qui est marqué comme public fait partie de l'API que toute personne utilisant votre classe/interface/autre utilisera et comptera.

  • protected - Ne vous y trompez pas, cela fait également partie de l'API! Les gens peuvent sous-classer, étendre votre code et utiliser tout ce qui est marqué comme protégé.

  • private - Les propriétés et méthodes privées peuvent être modifiées autant que vous le souhaitez. Personne d'autre ne peut les utiliser. Ce sont les seules choses que vous pouvez changer sans apporter de modifications radicales.

Ou en Semver termes:

  • Les modifications apportées à quoi que ce soit public ou protected devraient être considérées comme des modifications MAJEURES. 

  • Tout ce qui est nouveau public ou protected devrait être (au moins) MINOR

  • PATCH uniquement les modifications/modifications apportées à une variable private

Donc, en termes de maintenance du code, il est bon de faire attention à ce que vous faites public ou protected car ce sont les choses que vous promettez aux utilisateurs.

3
mcfedr

Lorsque nous suivons php orienté objet dans notre projet, nous devrions suivre certaines règles pour utiliser les modificateurs d'accès en php. Aujourd'hui, nous allons apprendre clairement ce qu'est le modificateur d'accès et comment l'utiliser. Les modificateurs d'accès PHP permettent de définir les droits d'accès avec les classes PHP et leurs membres, qui sont les fonctions et les variables définies dans la portée de la classe. En php, il existe trois champs d'application pour les membres de la classe.

  1. PUBLIQUE
  2. PRIVÉ
  3. PROTÉGÉ

Maintenant, regardons l’image suivante pour comprendre le niveau d’accès au modificateur d’accès  enter image description here

Voyons maintenant la liste suivante pour connaître les mots-clés PHP pouvant être utilisés comme modificateurs d'accès.

public: - la classe ou ses membres définis avec ce modificateur d'accès seront accessibles au public de n'importe où, même de l'extérieur du champ de la classe.

private: - les membres de la classe avec ce mot clé seront accessibles au sein de la classe elle-même. nous ne pouvons pas accéder aux données privées de la sous-classe. Il protège les membres des accès en dehors de la classe.

protected: - idem à private, sauf en autorisant les sous-classes à accéder aux membres protégés de la superclasse.

Maintenant, voyez le tableau pour comprendre le modificateur d'accès. Lire l'article complet php access modifire

1
Mahedi Hasan Durjoy

Public: est un état par défaut lorsque vous déclarez une variable ou une méthode, accessible directement à l’objet.

Protégé: accessible uniquement dans l'objet et les sous-classes.

Privé: ne peut être référencé que dans l'objet, pas dans les sous-classes.

1
Nomadme