variable - protected php




¿Cuál es la diferencia entre público, privado y protegido? (10)

¿Cuándo y por qué debo usar funciones y variables public , private y protected dentro de una clase? ¿Cuál es la diferencia entre ellos?

Ejemplos:

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

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

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

⚡️ Esta es una manera fácil de recordar el alcance de lo public , lo protected y lo private .

PUBLIC :

  • Ámbito public : una variable / función pública está disponible para objetos y otras clases.

PROTECTED :

  • alcance protected : una variable / función protegida está disponible para todas las clases que extienden la clase actual.
  • ¡No! Los objetos no pueden acceder a este ámbito.

PRIVATE :

  • Ámbito private : una variable / función privada solo es visible en la clase actual donde se está definiendo.
  • ¡No! La clase que extiende la clase actual no puede acceder a este ámbito.
  • ¡No! Los objetos no pueden acceder a este ámbito.

Lea la Visibilidad de un método o variable en el Manual de PHP.


El manual de PHP tiene una buena lectura sobre la pregunta aquí .

La visibilidad de una propiedad o método puede definirse prefijando la declaración con las palabras clave public, protected o private. Los miembros de la clase declarados públicos pueden ser accedidos en todas partes. Se puede acceder a los miembros declarados protegidos solo dentro de la propia clase y por clases heredadas y clases primarias. Los miembros declarados como privados solo pueden ser accedidos por la clase que define al miembro.


La diferencia es la siguiente:

Public : cualquier usuario o usuario de la clase puede acceder directamente a una variable o método público.

Protected : los usuarios de la clase no pueden acceder a una variable o método protegido, pero se puede acceder a ellos dentro de una subclase que hereda de la clase.

Private : solo se puede acceder a una variable o método privado desde la clase en la que está definida. Esto significa que no se puede llamar a una variable o método privado desde un elemento secundario que extiende la clase.


Las variables en PHP se emiten en tres tipos diferentes:

Público: los valores de estos tipos de variables están disponibles en todos los ámbitos y solicitan la ejecución de su código. declarar como: public $examTimeTable;

Privado: los valores de este tipo de variable solo están disponibles solo para la clase a la que pertenece. private $classRoomComputers;

Protegido: los valores de esta clase solo y solo están disponibles cuando el Acceso se otorgó en forma de herencia o de su clase secundaria. generalmente utilizado :: para conceder acceso por clase padre

protected $familyWealth;


Para mí, esta es la forma más útil de entender los tres tipos de propiedades:

Público : use esto cuando esté de acuerdo con que se acceda directamente a esta variable y se la modifique desde cualquier lugar en su código.

Ejemplo de uso desde fuera de la clase:

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

Protegido : use esto cuando quiera forzar a otros programadores (y a usted mismo) a usar getters / setters fuera de la clase al acceder y configurar variables (pero debe ser consistente y usar a los getters y setters dentro de la clase también). Esto o private tienden a ser la forma predeterminada en que debe configurar todas las propiedades de clase.

¿Por qué? Porque si decide en algún momento en el futuro (tal vez incluso en unos 5 minutos) que desea manipular el valor que se devuelve para esa propiedad o hacer algo con ella antes de obtener / configuración, puede hacer eso sin refactorizar en todas partes. Lo usé en tu proyecto.

Ejemplo de uso desde fuera de la clase:

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

Privado : private propiedades private son muy similares a protected propiedades protected . Pero la característica / diferencia distintiva es que hacerla private también hace que sea inaccesible para las clases secundarias sin utilizar el getter o setter de la clase primaria.

Básicamente, si está utilizando captadores y definidores para una propiedad (o si la clase principal la usa solo de forma interna y no está destinada a ser accesible en ningún otro lugar), también puede hacerlo private , solo para evitar que alguien pueda Tratando de usarlo directamente e introduciendo errores .

Ejemplo de uso dentro de una clase secundaria (que extiende MyObject):

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

Por lo general, se considera una buena práctica establecer la visibilidad más baja requerida, ya que esto promueve la encapsulación de datos y un buen diseño de la interfaz. Al considerar la variable de miembro y la visibilidad del método, piense en el papel que desempeña el miembro en la interacción con otros objetos.

Si usted "codifica una interfaz en lugar de una implementación", generalmente es bastante sencillo tomar decisiones de visibilidad. En general, las variables deben ser privadas o protegidas a menos que tenga una buena razón para exponerlas. Utilice los accesores públicos (captadores / setters) en lugar de limitar y regular el acceso a los aspectos internos de una clase.

Para usar un automóvil como una analogía, las cosas como la velocidad, la marcha y la dirección serían variables de instancia privada. No desea que el conductor manipule directamente cosas como la relación aire / combustible. En cambio, expones un número limitado de acciones como métodos públicos. La interfaz de un automóvil puede incluir métodos como accelerate() , deccelerate() / brake() , setGear() , turnLeft() , turnRight() , etc.

El conductor no sabe ni debe importarle cómo se implementan estas acciones en el interior del automóvil, y exponer esa funcionalidad podría ser peligroso para el conductor y otras personas en la carretera. De ahí la buena práctica de diseñar una interfaz pública y encapsular los datos detrás de esa interfaz.

Este enfoque también le permite alterar y mejorar la implementación de los métodos públicos en su clase sin romper el contrato de la interfaz con el código del cliente. Por ejemplo, podría mejorar el método de accelerate() para que sea más eficiente en el consumo de combustible, pero el uso de ese método seguirá siendo el mismo; el código del cliente no requeriría cambios, pero aún así obtendría los beneficios de su mejora de eficiencia.

Edición: como parece que todavía estás en medio de aprender conceptos orientados a objetos (que son mucho más difíciles de dominar que la sintaxis de cualquier idioma), te recomiendo encarecidamente que recojas una copia de Objetos, patrones y práctica de PHP de Matt Zandstra. Este es el libro que primero me enseñó a usar la POO de manera efectiva, en lugar de enseñarme la sintaxis. Había aprendido la sintaxis años antes, pero eso era inútil sin entender el "por qué" de la POO.


Reviviendo una vieja pregunta, pero creo que una muy buena manera de pensar esto es en términos de la API que está definiendo.

  • public : todo lo que está marcado como público es parte de la API que cualquier persona que use su clase / interfaz / otro usará y confiará.

  • protected - No te dejes engañar, ¡esto también es parte de la API! Las personas pueden crear subclases, ampliar su código y usar cualquier cosa marcada como protegida.

  • private : las propiedades y los métodos privados se pueden cambiar tanto como desee. Nadie más puede usar estos. Estas son las únicas cosas que puede cambiar sin hacer cambios de última hora.

O en términos de Semver :

  • Los cambios a cualquier cosa public o protected deben considerarse cambios PRINCIPALES.

  • Todo nuevo public o protected debe ser (al menos) MENOR

  • Solo los nuevos / cambios a algo private pueden ser PATCH

Entonces, en términos de mantener el código, es bueno tener cuidado con las cosas que hace public o protected porque estas son las cosas que promete a sus usuarios.


Teniendo en cuenta ' cuando ':
Tiendo a declarar todo como privado inicialmente, si no estoy muy seguro. La razón es que generalmente es mucho más fácil convertir un método privado en público que a la inversa. Esto se debe a que al menos puede estar seguro de que el método privado no se ha utilizado en ninguna otra parte que no sea la clase en sí. Es posible que un método público ya esté en uso en todas partes, posiblemente requiriendo una reescritura extensa.

Actualización : voy por un valor predeterminado de protected hoy en día, porque he llegado a encontrar que es lo suficientemente bueno para la encapsulación y no interfiere cuando extiendo clases (lo que trato de evitar de todos modos). Solo si tengo una buena razón para usar los otros dos, lo haré.

Una buena razón para un método private sería una que implemente algo inherente a ese objeto que incluso una clase extendida no debería cambiar (razón objetiva, además de la encapsulación, como la administración interna del estado). Eventualmente, todavía es bastante fácil rastrear dónde se usa un método protected lo general, por lo que actualmente estoy protected por defecto. Tal vez no sea 100% objetivo experiencia "en las trincheras", lo admito.


Ámbitos de visibilidad con ejemplos abstractos : facilita la comprensión

Esta visibilidad de una propiedad o método se define mediante una declaración previa al arreglo de una de las tres palabras clave (pública, protegida y privada)

Público : si una propiedad o método se define como público, significa que puede ser accedido y manipulado por cualquier cosa que pueda referirse a un objeto.

  • Resumen por ejemplo. Piense en el alcance de la visibilidad pública como un "picnic público" al que cualquiera puede acudir.

Protegido: cuando la visibilidad de una propiedad o método se establece en miembros protegidos, solo se puede acceder dentro de la clase en sí y por clases heredadas y heredadas. (Se hereda: una clase puede tener todas las propiedades y métodos de otra clase).

  • Piense como un ámbito de visibilidad protegido como "picnic de la compañía" donde los miembros de la compañía y sus familiares no pueden acceder al público. Es la restricción de alcance más común.

Privado: cuando la visibilidad de una propiedad o método se establece en privada, solo la clase que tiene miembros privados puede acceder a esos métodos y propiedades (Internamente dentro de la clase), a pesar de la relación de clase que haya.

  • con la analogía del picnic, piense como un "picnic de la compañía donde solo los miembros de la compañía están permitidos" en el picnic. No se permiten familiares ni público en general.

Público:

Cuando declara un método (función) o una propiedad (variable) como public , se puede acceder a esos métodos y propiedades a través de:

  • La misma clase que lo declaró.
  • Las clases que heredan la clase declarada anteriormente.
  • Cualquier elemento extraño fuera de esta clase también puede acceder a esas cosas.

Ejemplo:

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

Protegido:

Cuando declara un método (función) o una propiedad (variable) como protected , estos métodos y propiedades pueden ser accedidos por

  • La misma clase que lo declaró.
  • Las clases que heredan la clase declarada anteriormente.

Los miembros externos no pueden acceder a esas variables. "Forasteros" en el sentido de que no son instancias de objeto de la clase declarada.

Ejemplo:

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

El error exacto será este:

Error fatal de PHP: no se puede acceder a la propiedad protegida GrandPa :: $ nombre

Privado:

Cuando declara un método (función) o una propiedad (variable) como private , se puede acceder a esos métodos y propiedades a través de:

  • La misma clase que lo declaró.

Los miembros externos no pueden acceder a esas variables. Forasteros en el sentido de que no son instancias de objeto de la clase declarada e incluso las clases que heredan la clase declarada.

Ejemplo:

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

Los mensajes de error exactos serán:

Aviso: Propiedad indefinida: Papi :: $ nombre
Error grave: no se puede acceder a la propiedad privada GrandPa :: $ nombre

Disección de la clase del abuelo usando la Reflection

Este tema no está realmente fuera del alcance, y lo estoy agregando aquí solo para demostrar que la reflexión es realmente poderosa. Como dije en los tres ejemplos anteriores, no se puede acceder a private miembros protected y private (propiedades y métodos) fuera de la clase.

Sin embargo, con la reflexión, puede hacer lo extraordinario incluso al acceder a miembros protected y private fuera de la clase.

Bueno, ¿qué es la reflexión?

Reflexión agrega la capacidad de ingeniería inversa de clases, interfaces, funciones, métodos y extensiones. Además, ofrece formas de recuperar comentarios de documentos para funciones, clases y métodos.

Preámbulo

Tenemos una clase llamada Grandpas y decimos que tenemos tres propiedades. Para facilitar la comprensión, considere que hay tres abuelos con nombres:

  • Mark Henry
  • John Clash
  • Will Jones

Hagamos que ellos (asignen modificadores) sean public , protected y private respectivamente. Usted sabe muy bien que no se puede acceder a private miembros protected y private fuera de la clase. Ahora contradijamos la afirmación utilizando la reflexión.

El código

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

Salida:

#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

Conceptos erróneos comunes:

Por favor, no confunda con el siguiente ejemplo. Como se puede ver, no se puede acceder a los miembros private y protected fuera de la clase sin usar la reflexión

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

Salida:

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

Funciones de depuración

print_r , var_export y var_dump son funciones de depurador . Presentan información sobre una variable en una forma legible por humanos. Estas tres funciones revelarán las propiedades protected y private de los objetos con PHP 5. No se mostrarán los miembros de la clase estática.

Más recursos:





protected