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


Cuándo y por qué debería usar public, privatey protected funciones y variables 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() {
  // ...
}

832
2017-12-05 22:13


origen


Respuestas:


Tu usas:

  • public alcance para hacer que esa variable / función esté disponible desde cualquier lugar, otras clases e instancias del objeto.

  • private alcance cuando desea que su variable / función sea visible solo en su propia clase.

  • protected ámbito cuando desee que su variable / función sea visible en todas las clases que extienden la clase actual, incluida la clase principal.

Más: (Para información completa)


1080
2017-12-05 22:17



dd

Público:

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

  • La misma clase que lo declaró.
  • Las clases que heredan la clase declarada anterior.
  • 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, se puede acceder a esos métodos y propiedades

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

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

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 :: $ name


Privado:

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

  • 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 en sí e incluso las clases que heredar 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: Daddy :: $ name
  Error fatal: no se puede acceder a la propiedad privada GrandPa :: $ name


Diseccionando la Clase Grandpa usando Reflexión

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

Sin embargo, con la reflexión puedes hacer extraordinario incluso accediendo protected y private miembros fuera de la clase!

Bueno, ¿qué es el reflejo?

La reflexión agrega la capacidad de realizar ingeniería inversa en clases, interfaces,   funciones, métodos y extensiones. Además, ofrecen formas de   recuperar los comentarios de doc para funciones, clases y métodos.

Preámbulo

Tenemos una clase llamada Grandpas y decir que tenemos tres propiedades. Para una fácil comprensión, considere que hay tres grandpas con nombres:

  • Mark Henry
  • John Clash
  • Will Jones

Déjenos hacerlos (asignar modificadores) public, protected y private respectivamente. Tu sabes muy bien que protected y private no se puede acceder a los miembros fuera de la clase. Ahora vamos a contradecir la declaración usando 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 todavía puedes ver, el private y protectedmiembros no pueden ser accedidos fuera de 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 depuración. Presentan información sobre una variable en una forma legible por humanos. Estas tres funciones revelarán la protected y private propiedades de los objetos con PHP 5. Los miembros de la clase estática no ser mostrado.


Más recursos:



1015
2018-02-20 08:35



Por lo general, se considera una buena práctica establecer de manera predeterminada 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 miembro y la visibilidad del método, piense en el papel que desempeña el miembro en la interacción con otros objetos.

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

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

El conductor no sabe ni le debe importar cómo estas acciones son implementadas por el interior del automóvil, y exponer que la funcionalidad podría ser peligrosa para el conductor y otros en el camino. 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ías mejorar el accelerate() método para ser más eficiente en el uso de combustible, sin embargo, el uso de ese método sería el mismo; El código del cliente no requeriría cambios pero aún así cosecharía los beneficios de su mejora de eficiencia.

Editar: Dado que parece que todavía estás en medio de conceptos orientados a objetos de aprendizaje (que son mucho más difíciles de dominar que la sintaxis de ningún idioma), altamente recomiendo recoger una copia de Objetos, patrones y práctica de PHP por Matt Zandstra. Este es el libro que primero me enseñó cómo usar OOP de manera efectiva, en lugar de simplemente enseñarme la sintaxis. Había aprendido la sintaxis años antes, pero eso era inútil sin entender el "por qué" de OOP.


81
2017-09-03 20:17



privado: solo se puede acceder desde dentro de la clase

protected - se puede acceder desde dentro de la clase y clases INHERITING

público - se puede acceder desde el código FUERA de la clase también

Esto se aplica tanto a las funciones como a las variables.


69
2017-12-05 22:17



La diferencia es la siguiente:

Public :: Cualquier 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 ella dentro de una subclase que hereda de la clase.

Private :: Solo se puede acceder internamente a una variable o método privado desde la clase en la que está definido. Esto significa que no se puede llamar a una variable o método privado desde un niño que amplía la clase.


23
2017-09-03 19:51



Ámbitos de visibilidad con Ejemplos abstractos :: Facilita la comprensión

Esta visibilidad de una propiedad o método se define mediante la declaración previa a la fijación 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 tener acceso y ser manipulado por cualquier cosa que pueda referirse a un objeto.

  • Resumen eg. Piense en el alcance de la visibilidad pública como "picnic público" a quien cualquiera pueda acudir

Protegido: cuando se establece una visibilidad de propiedad o método para los miembros protegidos, solo se puede acceder dentro de la misma clase y por clases heredadas y heredadas. (Heredado: una clase puede tener todas las propiedades y métodos de otra clase).

  • Pensar como un alcance de visibilidad protegido como "Picnic de la compañía" donde los miembros de la compañía y sus familiares no están permitidos al público. Es la restricción de alcance más común.

Privado: Cuando una visibilidad de propiedad o método se configura como privada, solo la clase que tiene los 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 de picnic pensar como una "picnic de empresa donde solo los miembros de la compañía están permitidos" en el picnic ni la familia ni el público en general están permitidos.

15
2018-02-07 03:07



/**
 * 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

Extraído de :

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


14
2017-10-03 11:01



️ Aquí hay una manera fácil de recordar el alcance de public, protected y private.

PUBLIC:

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

PROTECTED:

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

PRIVATE:

  • private Alcance: 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 alcance.
  • ¡No! Los objetos no pueden acceder a este alcance.

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


8
2018-06-30 07:27



Considerando 'cuando':
Tiendo a declarar todo como privado inicialmente, si no estoy exactamente seguro. Por lo que respecta a la razón, es mucho más fácil convertir un método privado en público que al revés. Esto se debe a que al menos puede estar seguro de que el método privado no se haya utilizado en ningún otro lugar, sino en la clase misma. Es posible que ya se utilice un método público en todas partes, lo que posiblemente requiera una relectura extensa.

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

Una buena razón para un private El método sería uno que implementa algo inherente a ese objeto que incluso una clase extendida no debería cambiar (razón de hecho, además de la encapsulación, como la gestión interna del estado). Finalmente, todavía es fácil localizar dónde protected método se usa generalmente, así que de manera predeterminada protected hoy en día. Quizás no sea una experiencia 100% objetiva "en las trincheras", lo admito.


8
2018-05-28 14:27



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

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


6
2017-12-05 22:16