classes - static public private protected php




Qual è la differenza tra pubblico, privato e protetto? (10)

⚡️ Ecco un modo semplice per ricordare l'ambito di public , protected e private .

PUBLIC :

  • ambito public : una variabile / funzione pubblica è disponibile per entrambi gli oggetti e altre classi.

PROTECTED :

  • ambito protected : una variabile / funzione protetta è disponibile per tutte le classi che estendono la classe corrente.
  • No! Gli oggetti non possono accedere a questo ambito

PRIVATE :

  • ambito private : una variabile / funzione privata è visibile solo nella classe corrente in cui viene definita.
  • No! Le classi che estendono la classe corrente non possono accedere a questo ambito.
  • No! Gli oggetti non possono accedere a questo ambito.

Leggi la Visibilità di un metodo o di una variabile su PHP Manual.

Quando e perché dovrei usare funzioni e variabili public , private e protected all'interno di una classe? Qual'è la differenza tra loro?

Esempi:

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

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

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

Considerando ' quando ':
Tendo a dichiarare tutto come privato inizialmente, se non sono esattamente sicuro. Essendo la ragione, di solito è molto più semplice trasformare un metodo privato pubblico rispetto al contrario. Questo perché puoi almeno essere sicuro che il metodo privato non è stato usato da nessuna parte ma nella classe stessa. Un metodo pubblico potrebbe essere già in uso ovunque, eventualmente richiedendo un'ampia riscrittura.

Aggiornamento : per impostazione predefinita sono protected al momento, perché ho scoperto che è sufficiente per l'incapsulamento e non interferisce con l'estensione delle classi (che comunque cerco di evitare). Solo se avrò una buona ragione per usare gli altri due, lo farò.

Una buona ragione per un metodo private sarebbe quella che implementa qualcosa di inerente a quell'oggetto che anche una classe che si estende non dovrebbe cambiare (motivo fattuale, oltre all'incapsulamento, come la gestione dello stato interno). Alla fine, è ancora abbastanza facile rintracciare dove viene utilizzato un metodo protected solito, quindi sono protected modo predefinito al giorno d'oggi. Forse non il 100% obiettivo dell'esperienza "nelle trincee", lo ammetto.


In genere, è considerata buona pratica l'impostazione predefinita per la visibilità minima richiesta, in quanto ciò promuove l'incapsulamento dei dati e una buona progettazione dell'interfaccia. Quando si considera la variabile membro e la visibilità del metodo, si pensi al ruolo che il membro gioca nell'interazione con altri oggetti.

Se si "codifica su un'interfaccia anziché su un'implementazione", di solito è piuttosto semplice prendere decisioni sulla visibilità. In generale, le variabili dovrebbero essere private o protette a meno che non si abbia una buona ragione per esporle. Utilizzare accessorie pubbliche (getter / setter) per limitare e regolare l'accesso agli interni di una classe.

Per usare un'auto come un'analogia, cose come velocità, marcia e direzione sarebbero variabili di istanze private. Non vuoi che il guidatore manipoli direttamente cose come il rapporto aria / carburante. Invece, esponi un numero limitato di azioni come metodi pubblici. L'interfaccia per un'automobile potrebbe includere metodi come accelerate() , deccelerate() / brake() , setGear() , turnLeft() , turnRight() , ecc.

Il guidatore non sa né dovrebbe preoccuparsi di come queste azioni siano implementate dagli interni dell'auto, e l'esposizione di tale funzionalità potrebbe essere pericolosa per il guidatore e gli altri sulla strada. Da qui la buona pratica di progettare un'interfaccia pubblica e incapsulare i dati dietro quella interfaccia.

Questo approccio consente inoltre di modificare e migliorare l'implementazione dei metodi pubblici nella classe senza interrompere il contratto dell'interfaccia con il codice client. Ad esempio, è possibile migliorare il metodo accelerate() per essere più efficiente in termini di consumo di carburante, tuttavia l'utilizzo di tale metodo rimarrebbe lo stesso; il codice cliente non richiederebbe modifiche ma raccoglierà ancora i benefici del miglioramento dell'efficienza.

Modifica: Dal momento che sembra che tu stia ancora nel mezzo di concetti di apprendimento orientato agli oggetti (che sono molto più difficili da padroneggiare della sintassi di qualsiasi lingua), consiglio vivamente di prendere una copia di PHP Oggetti, Pattern e Pratica di Matt Zandstra. Questo è il libro che per primo mi ha insegnato come utilizzare efficacemente OOP, piuttosto che insegnarmi la sintassi. Avevo imparato la sintassi anni prima, ma era inutile senza capire il "perché" di OOP.


La differenza è la seguente:

Public :: Una variabile o un metodo pubblico è accessibile direttamente da qualsiasi utente della classe.

Protected : non è possibile accedere a una variabile oa un metodo protetto dagli utenti della classe, ma è possibile accedervi all'interno di una sottoclasse che eredita dalla classe.

Private :: Una variabile o un metodo privato è accessibile solo internamente dalla classe in cui è definito. Ciò significa che non è possibile chiamare una variabile privata o un metodo da un figlio che estende la classe.


Per me, questo è il modo più utile per comprendere i tre tipi di proprietà:

Pubblico : usalo quando sei a posto con questa variabile a cui si accede direttamente e cambiata da qualsiasi punto del codice.

Esempio di utilizzo dall'esterno della classe:

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

Protetto : usalo quando vuoi forzare altri programmatori (e te stesso) a usare getter / setter al di fuori della classe quando accedono e impostano le variabili (ma dovresti essere coerente e usare anche i getter ei setter all'interno della classe). Questo o private tendono ad essere il modo predefinito in cui è necessario impostare tutte le proprietà della classe.

Perché? Perché se decidi in un momento successivo (forse anche in 5 minuti) di manipolare il valore restituito per quella proprietà o di fare qualcosa con esso prima di ottenere / impostare, puoi farlo senza refactoring ovunque tu abbia usato nel tuo progetto.

Esempio di utilizzo dall'esterno della classe:

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

Privato : private proprietà private sono molto simili alle proprietà protected . Ma la caratteristica distintiva / differenza è che renderla private rende anche inaccessibile le classi figlio senza usare il getter o setter della classe genitore.

Quindi, in pratica, se stai usando getter e setter per una proprietà (o se è usata solo internamente dalla classe genitore e non è pensata per essere accessibile da nessun'altra parte) potresti anche renderla private , solo per impedire a chiunque di cercando di usarlo direttamente e introducendo bug .

Esempio di utilizzo all'interno di una classe figlia (che estende MyObject):

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

Pubblico: è uno stato predefinito quando si dichiara una variabile o un metodo, a cui è possibile accedere direttamente da qualsiasi oggetto.

Protetto: è possibile accedere solo all'interno dell'oggetto e delle sottoclassi.

Privato: può essere fatto riferimento solo all'interno dell'oggetto, non in sottoclassi.



Usate:

  • ambito public per rendere tale variabile / funzione disponibile da qualsiasi luogo, da altre classi e istanze dell'oggetto.

  • ambito private quando vuoi che la tua variabile / funzione sia visibile solo nella sua classe.

  • ambito protected quando si desidera rendere visibile la propria variabile / funzione in tutte le classi che estendono la classe corrente inclusa la classe genitore.

Altro: (Per informazioni complete)


Ambiti di visibilità con esempi astratti :: Semplifica la comprensione

Questa visibilità di una proprietà o di un metodo è definita dalla dichiarazione di pre-fixing di una delle tre parole chiave (pubblica, protetta e privata)

Pubblico : se una proprietà o un metodo è definito pubblico, significa che può essere sia accessibile che manipolato da qualsiasi cosa possa riferirsi all'oggetto.

  • Ad es. Pensa all'ambito della visibilità pubblica come a un "picnic pubblico" a cui chiunque può partecipare.

Protetto: quando una visibilità di proprietà o metodo è impostata su membri protetti, è possibile accedere solo alla classe stessa e alle classi ereditate ed ereditanti. (Ereditato: - una classe può avere tutte le proprietà e i metodi di un'altra classe).

  • Pensa come uno spazio di visibilità protetto come "Picnic aziendale" in cui i membri dell'azienda e i loro familiari non sono ammessi al pubblico. È la restrizione di ambito più comune.

Privato: quando una visibilità di proprietà o metodo è impostata su private, solo la classe che ha i membri privati ​​può accedere a tali metodi e proprietà (internamente all'interno della classe), nonostante la relazione di classe eventualmente esistente.

  • con l'analogia con il picnic si pensa a un "picnic aziendale in cui solo i membri dell'azienda sono ammessi" nel picnic. non la famiglia né il grande pubblico sono ammessi.

Pubblico:

Quando dichiari un metodo (funzione) o una proprietà (variabile) come public , è possibile accedere a tali metodi e proprietà:

  • La stessa classe che l'ha dichiarata.
  • Le classi che ereditano la classe dichiarata sopra.
  • Qualsiasi elemento estraneo al di fuori di questa classe può anche accedere a queste cose.

Esempio:

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

protetto:

Quando si dichiara un metodo (funzione) o una proprietà (variabile) come protected , è possibile accedere a tali metodi e proprietà

  • La stessa classe che l'ha dichiarata.
  • Le classi che ereditano la classe dichiarata sopra.

I membri Outsider non possono accedere a tali variabili. "Outsiders" nel senso che non sono istanze oggetto della classe dichiarata stessa.

Esempio:

<?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'errore esatto sarà questo:

Errore irreversibile PHP: impossibile accedere alla proprietà protetta GrandPa :: $ name

Privato:

Quando dichiari un metodo (funzione) o una proprietà (variabile) come private , è possibile accedere a tali metodi e proprietà:

  • La stessa classe che l'ha dichiarata.

I membri Outsider non possono accedere a tali variabili. Outsider nel senso che non sono istanze di oggetti della classe dichiarata stessa e persino delle classi che ereditano la classe dichiarata.

Esempio:

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

I messaggi di errore esatti saranno:

Avviso: Proprietà non definita: Daddy :: $ name
Errore irreversibile: impossibile accedere alla proprietà privata GrandPa :: $ name

Dissecting the Grandpa Class usando Reflection

Questo argomento non è davvero fuori portata, e lo sto aggiungendo qui solo per dimostrare che la riflessione è davvero potente. Come ho affermato nei tre esempi precedenti, non è possibile accedere private membri protected e private (proprietà e metodi) al di fuori della classe.

Tuttavia, con la riflessione puoi fare l' extra-ordinario anche accedendo a membri protected e private al di fuori della classe!

Bene, cos'è il riflesso?

Reflection aggiunge la capacità di decodificare classi, interfacce, funzioni, metodi ed estensioni. Inoltre, offrono modi per recuperare i commenti del doc per funzioni, classi e metodi.

Preambolo

Abbiamo una classe chiamata Grandpas e diciamo che abbiamo tre proprietà. Per una facile comprensione, si consideri che ci sono tre nonni con nomi:

  • Mark Henry
  • John Clash
  • Will Jones

Cerchiamo di renderli (assegnare modificatori) public , protected e private rispettivamente. Sai benissimo che private membri protected e private non sono accessibili al di fuori della classe. Ora contraddiciamo l'affermazione usando la riflessione.

Il codice

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

Produzione:

#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

Idee sbagliate comuni:

Si prega di non confondere con l'esempio di seguito. Come puoi ancora vedere, non è possibile accedere ai membri private e protected al di fuori della classe senza utilizzare la reflection

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

Produzione:

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

Funzioni di debug

print_r , var_export e var_dump sono funzioni di debugger . Presentano informazioni su una variabile in una forma leggibile dall'uomo. Queste tre funzioni rivelano le proprietà protected e private degli oggetti con PHP 5. I membri delle classi statiche non verranno mostrati.

Altre risorse:





protected