diff --git a/language/oop5/magic.xml b/language/oop5/magic.xml
new file mode 100644
index 000000000..a8a5ee699
--- /dev/null
+++ b/language/oop5/magic.xml
@@ -0,0 +1,631 @@
+
+
+
+ Metodi magici
+
+ I metodi magici sono metodi speciali che sovrascrivono l'azione predefinita
+ di PHP quando vengono eseguite determinate azioni su un oggetto.
+
+
+
+ Tutti i nomi di metodi che iniziano con __ sono riservati
+ da PHP. Pertanto, non è consigliato usare tali nomi di metodi a meno che
+ non si voglia sovrascrivere il comportamento di PHP.
+
+
+
+ I seguenti nomi di metodi sono considerati magici:
+
+ __construct(),
+ __destruct(),
+ __call(),
+ __callStatic(),
+ __get(),
+ __set(),
+ __isset(),
+ __unset(),
+ __sleep(),
+ __wakeup(),
+ __serialize(),
+ __unserialize(),
+ __toString(),
+ __invoke(),
+ __set_state(),
+ __clone() e
+ __debugInfo().
+
+
+
+
+
+ Tutti i metodi magici, ad eccezione di
+ __construct(),
+ __destruct() e
+ __clone(),
+ devono essere dichiarati come public,
+ altrimenti viene emesso un E_WARNING.
+ Prima di PHP 8.0.0, non veniva emessa alcuna diagnostica per i metodi magici
+ __sleep(),
+ __wakeup(),
+ __serialize(),
+ __unserialize() e
+ __set_state().
+
+
+
+
+ Se vengono usate dichiarazioni di tipo nella definizione di un metodo
+ magico, queste devono essere identiche alla firma descritta in questo
+ documento. Altrimenti, viene emesso un errore fatale.
+ Prima di PHP 8.0.0, non veniva emessa alcuna diagnostica.
+ Tuttavia, __construct() e
+ __destruct() non devono dichiarare
+ un tipo di ritorno; altrimenti viene emesso un errore fatale.
+
+
+
+
+
+ __sleep() e
+ __wakeup()
+
+
+
+ publicarray__sleep
+
+
+
+ publicvoid__wakeup
+
+
+
+
+ serialize verifica se la classe ha una funzione con
+ il nome magico __sleep(). In tal caso,
+ quella funzione viene eseguita prima di qualsiasi serializzazione. Può
+ ripulire l'oggetto e deve restituire un array con i nomi di tutte le
+ variabili di quell'oggetto che devono essere serializzate.
+ Se il metodo non restituisce nulla, viene serializzato &null; e viene
+ emesso un E_NOTICE.
+
+
+
+ Non è possibile per __sleep()
+ restituire nomi di proprietà private nelle classi genitore. Farlo
+ produrrà un errore di livello E_NOTICE.
+ Usare __serialize() al suo posto.
+
+
+
+
+ A partire da PHP 8.0.0, la restituzione di un valore che non è un array
+ da __sleep() genera un avviso.
+ In precedenza, generava una notifica.
+
+
+
+ L'uso previsto di __sleep() è quello di
+ salvare i dati in sospeso o eseguire operazioni di pulizia simili. Inoltre,
+ la funzione è utile se un oggetto molto grande non ha bisogno di essere
+ salvato completamente.
+
+
+ Al contrario, unserialize verifica la presenza di una
+ funzione con il nome magico
+ __wakeup(). Se presente, questa
+ funzione può ricostruire qualsiasi risorsa che l'oggetto potrebbe avere.
+
+
+ L'uso previsto di __wakeup() è quello
+ di ristabilire qualsiasi connessione al database che potrebbe essere stata
+ persa durante la serializzazione e di eseguire altre operazioni di
+ reinizializzazione.
+
+
+ Sleep e wakeup
+
+dsn = $dsn;
+ $this->username = $username;
+ $this->password = $password;
+ $this->connect();
+ }
+
+ private function connect()
+ {
+ $this->link = new PDO($this->dsn, $this->username, $this->password);
+ }
+
+ public function __sleep()
+ {
+ return array('dsn', 'username', 'password');
+ }
+
+ public function __wakeup()
+ {
+ $this->connect();
+ }
+}?>
+]]>
+
+
+
+
+
+
+ __serialize() e
+ __unserialize()
+
+
+
+ publicarray__serialize
+
+
+
+ publicvoid__unserialize
+ arraydata
+
+
+
+ serialize verifica se la classe ha una funzione con
+ il nome magico __serialize(). In
+ tal caso, quella funzione viene eseguita prima di qualsiasi
+ serializzazione. Deve costruire e restituire un array associativo di coppie
+ chiave/valore che rappresentano la forma serializzata dell'oggetto. Se non
+ viene restituito alcun array, verrà lanciato un
+ TypeError.
+
+
+
+ Se sia __serialize() che
+ __sleep() sono definiti nello stesso
+ oggetto, solo __serialize() verrà
+ chiamato. __sleep() verrà ignorato. Se
+ l'oggetto implementa l'interfaccia
+ Serializable, il metodo
+ serialize() dell'interfaccia verrà ignorato e verrà
+ usato __serialize() al suo posto.
+
+
+
+ L'uso previsto di __serialize() è
+ quello di definire una rappresentazione arbitraria dell'oggetto adatta alla
+ serializzazione. Gli elementi dell'array possono corrispondere alle
+ proprietà dell'oggetto, ma non è obbligatorio.
+
+
+ Al contrario, unserialize verifica la presenza di una
+ funzione con il nome magico
+ __unserialize(). Se presente,
+ a questa funzione verrà passato l'array ripristinato che era stato
+ restituito da __serialize(). Potrà
+ quindi ripristinare le proprietà dell'oggetto da quell'array come
+ appropriato.
+
+
+
+ Se sia __unserialize() che
+ __wakeup() sono definiti nello stesso
+ oggetto, solo __unserialize()
+ verrà chiamato. __wakeup() verrà
+ ignorato.
+
+
+
+
+ Questa funzionalità è disponibile a partire da PHP 7.4.0.
+
+
+
+ Serialize e unserialize
+
+dsn = $dsn;
+ $this->username = $username;
+ $this->password = $password;
+ $this->connect();
+ }
+
+ private function connect()
+ {
+ $this->link = new PDO($this->dsn, $this->username, $this->password);
+ }
+
+ public function __serialize(): array
+ {
+ return [
+ 'dsn' => $this->dsn,
+ 'user' => $this->username,
+ 'pass' => $this->password,
+ ];
+ }
+
+ public function __unserialize(array $data): void
+ {
+ $this->dsn = $data['dsn'];
+ $this->username = $data['user'];
+ $this->password = $data['pass'];
+
+ $this->connect();
+ }
+}?>
+]]>
+
+
+
+
+
+ __toString()
+
+ publicstring__toString
+
+
+
+ Il metodo __toString() permette a
+ una classe di decidere come comportarsi quando viene trattata come una
+ stringa. Ad esempio, cosa stamperà echo $obj;.
+
+
+
+ A partire da PHP 8.0.0, il valore di ritorno segue la semantica standard
+ dei tipi PHP, il che significa che verrà convertito in una
+ string se possibile e se la
+ tipizzazione stretta
+ è disabilitata.
+
+
+ Un oggetto Stringable
+ non sarà accettato da una dichiarazione di tipo
+ string se la
+ tipizzazione stretta
+ è abilitata. Se si desidera questo comportamento, la dichiarazione di tipo
+ deve accettare Stringable e
+ string tramite un tipo unione.
+
+
+ A partire da PHP 8.0.0, qualsiasi classe che contiene un metodo
+ __toString() implementerà anche
+ implicitamente l'interfaccia Stringable, e
+ quindi supererà i controlli di tipo per quell'interfaccia. Si raccomanda
+ comunque di implementare esplicitamente l'interfaccia.
+
+
+ In PHP 7.4, il valore restituito deve essere una
+ string, altrimenti viene lanciato un
+ Error.
+
+
+ Prima di PHP 7.4.0, il valore restituito deve essere
+ una string, altrimenti viene emesso un errore fatale
+ E_RECOVERABLE_ERROR.
+
+
+
+
+ Non era possibile lanciare un'eccezione dall'interno di un metodo
+ __toString()
+ prima di PHP 7.4.0. Farlo causava un errore fatale.
+
+
+
+ Esempio semplice
+
+foo = $foo;
+ }
+
+ public function __toString()
+ {
+ return $this->foo;
+ }
+}
+
+$class = new TestClass('Hello');
+echo $class;
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+
+ __invoke()
+
+ mixed__invoke
+ values
+
+
+ Il metodo __invoke() viene chiamato
+ quando uno script tenta di chiamare un oggetto come una funzione.
+
+
+ Utilizzo di __invoke()
+
+
+]]>
+
+ &example.outputs;
+
+
+
+
+
+ Utilizzo di __invoke()
+
+key = $key;
+ }
+
+ public function __invoke(array $a, array $b): int
+ {
+ return $a[$this->key] <=> $b[$this->key];
+ }
+}
+
+$customers = [
+ ['id' => 1, 'first_name' => 'John', 'last_name' => 'Do'],
+ ['id' => 3, 'first_name' => 'Alice', 'last_name' => 'Gustav'],
+ ['id' => 2, 'first_name' => 'Bob', 'last_name' => 'Filipe']
+];
+
+// ordina i clienti per nome
+usort($customers, new Sort('first_name'));
+print_r($customers);
+
+// ordina i clienti per cognome
+usort($customers, new Sort('last_name'));
+print_r($customers);
+?>
+]]>
+
+ &example.outputs;
+
+ Array
+ (
+ [id] => 3
+ [first_name] => Alice
+ [last_name] => Gustav
+ )
+
+ [1] => Array
+ (
+ [id] => 2
+ [first_name] => Bob
+ [last_name] => Filipe
+ )
+
+ [2] => Array
+ (
+ [id] => 1
+ [first_name] => John
+ [last_name] => Do
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [id] => 1
+ [first_name] => John
+ [last_name] => Do
+ )
+
+ [1] => Array
+ (
+ [id] => 2
+ [first_name] => Bob
+ [last_name] => Filipe
+ )
+
+ [2] => Array
+ (
+ [id] => 3
+ [first_name] => Alice
+ [last_name] => Gustav
+ )
+
+)
+]]>
+
+
+
+
+
+ __set_state()
+
+ staticobject__set_state
+ arrayproperties
+
+
+ Questo metodo statico viene
+ chiamato per le classi esportate da var_export.
+
+
+ L'unico parametro di questo metodo è un array contenente le proprietà
+ esportate nella forma ['property' => value, ...].
+
+
+ Utilizzo di __set_state()
+
+var1 = $an_array['var1'];
+ $obj->var2 = $an_array['var2'];
+ return $obj;
+ }
+}
+
+$a = new A;
+$a->var1 = 5;
+$a->var2 = 'foo';
+
+$b = var_export($a, true);
+var_dump($b);
+eval('$c = ' . $b . ';');
+var_dump($c);
+?>
+]]>
+
+ &example.outputs;
+
+ 5,
+ 'var2' => 'foo',
+))"
+object(A)#2 (2) {
+ ["var1"]=>
+ int(5)
+ ["var2"]=>
+ string(3) "foo"
+}
+]]>
+
+
+
+
+ Quando si esporta un oggetto, var_export non verifica
+ se __set_state() è implementato
+ dalla classe dell'oggetto, quindi la reimportazione di oggetti risulterà
+ in un'eccezione Error, se __set_state() non è
+ implementato. In particolare, questo riguarda alcune classi interne.
+
+
+ È responsabilità del programmatore verificare che vengano reimportati solo
+ oggetti la cui classe implementa __set_state().
+
+
+
+
+
+ __debugInfo()
+
+ array__debugInfo
+
+
+
+ Questo metodo viene chiamato da var_dump durante il
+ dump di un oggetto per ottenere le proprietà che devono essere mostrate. Se
+ il metodo non è definito su un oggetto, verranno mostrate tutte le
+ proprietà pubbliche, protette e private.
+
+
+ Utilizzo di __debugInfo()
+
+prop = $val;
+ }
+
+ public function __debugInfo() {
+ return [
+ 'propSquared' => $this->prop ** 2,
+ ];
+ }
+}
+
+var_dump(new C(42));
+?>
+]]>
+
+ &example.outputs;
+
+
+ int(1764)
+}
+]]>
+
+
+
+
+
diff --git a/language/oop5/overloading.xml b/language/oop5/overloading.xml
new file mode 100644
index 000000000..859784b39
--- /dev/null
+++ b/language/oop5/overloading.xml
@@ -0,0 +1,335 @@
+
+
+
+ Overloading
+
+
+ L'overloading in PHP fornisce i mezzi per
+ creare dinamicamente proprietà e metodi.
+ Queste entità dinamiche vengono elaborate tramite metodi magici
+ che è possibile definire in una classe per vari tipi di azioni.
+
+
+
+ I metodi di overloading vengono invocati quando si interagisce con
+ proprietà o metodi che non sono stati dichiarati o che non sono
+ visibili nello
+ scope corrente. Il resto di questa sezione userà i termini
+ proprietà inaccessibili e metodi
+ inaccessibili per riferirsi a questa combinazione di
+ dichiarazione e visibilità.
+
+
+
+ Tutti i metodi di overloading devono essere definiti come
+ public.
+
+
+
+
+ Nessuno degli argomenti di questi metodi magici può essere
+ passato per
+ riferimento.
+
+
+
+
+
+ L'interpretazione di PHP dell'overloading è
+ diversa dalla maggior parte dei linguaggi orientati agli oggetti.
+ L'overloading tradizionalmente fornisce la possibilità di avere
+ più metodi con lo stesso nome ma con quantità e tipi di argomenti
+ differenti.
+
+
+
+
+ Overloading delle proprietà
+
+
+ publicvoid__set
+ stringname
+ mixedvalue
+
+
+ publicmixed__get
+ stringname
+
+
+ publicbool__isset
+ stringname
+
+
+ publicvoid__unset
+ stringname
+
+
+
+ __set() viene eseguito quando si scrivono
+ dati in proprietà inaccessibili (protette o private) o inesistenti.
+
+
+
+ __get() viene utilizzato per leggere
+ dati da proprietà inaccessibili (protette o private) o inesistenti.
+
+
+
+ __isset() viene attivato chiamando
+ isset o empty
+ su proprietà inaccessibili (protette o private) o inesistenti.
+
+
+
+ __unset() viene invocato quando
+ unset viene usato su proprietà inaccessibili
+ (protette o private) o inesistenti.
+
+
+
+ L'argomento $name è il nome della proprietà con cui
+ si interagisce. L'argomento $value del metodo
+ __set() specifica il valore a cui la
+ proprietà $name deve essere impostata.
+
+
+
+ L'overloading delle proprietà funziona solo nel contesto dell'oggetto.
+ Questi metodi magici non verranno attivati nel contesto statico. Pertanto
+ questi metodi non devono essere dichiarati
+ static.
+ Viene emesso un avviso se uno dei metodi magici di overloading
+ viene dichiarato static.
+
+
+
+
+ Il valore di ritorno di __set() viene
+ ignorato a causa del modo in cui PHP elabora l'operatore di assegnazione.
+ Allo stesso modo, __get() non viene mai
+ chiamato quando si concatenano le assegnazioni in questo modo:
+ b = 8; ]]>
+
+
+
+
+
+ PHP non chiamerà un metodo di overloading dall'interno dello stesso metodo
+ di overloading. Ciò significa, ad esempio, che scrivere
+ return $this->foo all'interno di
+ __get() restituirà null
+ e genererà un E_WARNING se non esiste una proprietà
+ foo definita, piuttosto che chiamare
+ __get() una seconda volta.
+ Tuttavia, i metodi di overloading possono invocare altri metodi di
+ overloading implicitamente (come
+ __set() che attiva
+ __get()).
+
+
+
+
+
+ Overloading delle proprietà tramite i metodi __get(),
+ __set(), __isset()
+ e __unset()
+
+
+data[$name] = $value;
+ }
+
+ public function __get($name)
+ {
+ echo "Getting '$name'\n";
+ if (array_key_exists($name, $this->data)) {
+ return $this->data[$name];
+ }
+
+ $trace = debug_backtrace();
+ trigger_error(
+ 'Undefined property via __get(): ' . $name .
+ ' in ' . $trace[0]['file'] .
+ ' on line ' . $trace[0]['line'],
+ E_USER_NOTICE);
+ return null;
+ }
+
+ public function __isset($name)
+ {
+ echo "Is '$name' set?\n";
+ return isset($this->data[$name]);
+ }
+
+ public function __unset($name)
+ {
+ echo "Unsetting '$name'\n";
+ unset($this->data[$name]);
+ }
+
+ /** Non è un metodo magico, è qui solo come esempio. */
+ public function getHidden()
+ {
+ return $this->hidden;
+ }
+}
+
+
+$obj = new PropertyTest;
+
+$obj->a = 1;
+echo $obj->a . "\n\n";
+
+var_dump(isset($obj->a));
+unset($obj->a);
+var_dump(isset($obj->a));
+echo "\n";
+
+echo $obj->declared . "\n\n";
+
+echo "Let's experiment with the private property named 'hidden':\n";
+echo "Privates are visible inside the class, so __get() not used...\n";
+echo $obj->getHidden() . "\n";
+echo "Privates not visible outside of class, so __get() is used...\n";
+echo $obj->hidden . "\n";
+?>
+]]>
+
+ &example.outputs;
+
+ on line 70 in on line 29
+]]>
+
+
+
+
+
+
+ Overloading dei metodi
+
+
+ publicmixed__call
+ stringname
+ arrayarguments
+
+
+ public staticmixed__callStatic
+ stringname
+ arrayarguments
+
+
+
+ __call() viene attivato quando si
+ invocano metodi inaccessibili nel contesto di un oggetto.
+
+
+
+ __callStatic() viene attivato
+ quando si invocano metodi inaccessibili nel contesto statico.
+
+
+
+ L'argomento $name è il nome del metodo che viene
+ chiamato. L'argomento $arguments è un array enumerativo
+ contenente i parametri passati al metodo $name.
+
+
+
+
+ Overloading dei metodi tramite i metodi __call()
+ e __callStatic()
+
+
+ runTest('in object context');
+
+MethodTest::runTest('in static context');
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+
+
+
diff --git a/language/oop5/traits.xml b/language/oop5/traits.xml
new file mode 100644
index 000000000..44b8b10de
--- /dev/null
+++ b/language/oop5/traits.xml
@@ -0,0 +1,711 @@
+
+
+
+ Trait
+
+ PHP implementa un modo per riutilizzare il codice chiamato Trait.
+
+
+ I Trait sono un meccanismo per il riutilizzo del codice nei linguaggi a
+ ereditarietà singola come PHP. Un Trait è pensato per ridurre alcune
+ limitazioni dell'ereditarietà singola permettendo a uno sviluppatore di
+ riutilizzare liberamente insiemi di metodi in diverse classi indipendenti
+ che vivono in diverse gerarchie di classi. La semantica della combinazione
+ di Trait e classi è definita in modo da ridurre la complessità ed evitare
+ i tipici problemi associati all'ereditarietà multipla e ai Mixin.
+
+
+ Un Trait è simile a una classe, ma è pensato solo per raggruppare
+ funzionalità in modo granulare e coerente. Non è possibile istanziare un
+ Trait da solo. È un'aggiunta all'ereditarietà tradizionale e permette la
+ composizione orizzontale del comportamento; ovvero, l'applicazione di
+ membri di classe senza richiedere l'ereditarietà.
+
+
+ Esempio di Trait
+
+sayHello();
+ echo ' ';
+ $this->sayWorld();
+ echo "!\n";
+ }
+}
+
+$myHelloWorld = new MyHelloWorld();
+$myHelloWorld->sayHelloWorld();
+
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+ Precedenza
+
+ Un membro ereditato da una classe base viene sovrascritto da un membro
+ inserito da un Trait. L'ordine di precedenza è che i membri della classe
+ corrente sovrascrivono i metodi del Trait, che a loro volta sovrascrivono
+ i metodi ereditati.
+
+
+ Esempio di ordine di precedenza
+
+ Un metodo ereditato da una classe base viene sovrascritto dal metodo
+ inserito in MyHelloWorld dal Trait SayWorld. Il comportamento è lo stesso
+ per i metodi definiti nella classe MyHelloWorld. L'ordine di precedenza
+ è che i metodi della classe corrente sovrascrivono i metodi del Trait,
+ che a loro volta sovrascrivono i metodi della classe base.
+
+
+sayHello();
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+ Esempio alternativo di ordine di precedenza
+
+sayHello();
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+
+ Trait multipli
+
+ È possibile inserire più Trait in una classe elencandoli nell'istruzione
+ use, separati da virgole.
+
+
+ Utilizzo di Trait multipli
+
+sayHello();
+$o->sayWorld();
+$o->sayExclamationMark();
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+
+ Risoluzione dei conflitti
+
+ Se due Trait inseriscono un metodo con lo stesso nome, viene prodotto un
+ errore fatale se il conflitto non viene risolto esplicitamente.
+
+
+ Per risolvere i conflitti di denominazione tra Trait utilizzati nella stessa
+ classe, è necessario usare l'operatore insteadof per
+ scegliere esattamente uno dei metodi in conflitto.
+
+
+ Poiché questo permette solo di escludere metodi, l'operatore
+ as può essere usato per aggiungere un alias a uno dei
+ metodi. Si noti che l'operatore as non rinomina il
+ metodo e non influisce su nessun altro metodo.
+
+
+ Risoluzione dei conflitti
+
+ In questo esempio, Talker usa i trait A e B.
+ Poiché A e B hanno metodi in conflitto, viene definito di usare
+ la variante di smallTalk dal trait B, e la variante di bigTalk dal
+ trait A.
+
+
+ Aliased_Talker fa uso dell'operatore as
+ per poter usare l'implementazione di bigTalk di B con un alias
+ aggiuntivo talk.
+
+
+
+]]>
+
+
+
+
+
+ Modifica della visibilità dei metodi
+
+ Utilizzando la sintassi as, è anche possibile regolare
+ la visibilità del metodo nella classe che lo espone.
+
+
+ Modifica della visibilità dei metodi
+
+
+]]>
+
+
+
+
+
+ Trait composti da Trait
+
+ Così come le classi possono usare i trait, anche altri trait possono farlo.
+ Usando uno o più trait nella definizione di un trait, questo può essere
+ composto parzialmente o interamente dai membri definiti in quegli altri trait.
+
+
+ Trait composti da Trait
+
+sayHello();
+$o->sayWorld();
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+
+
+ Membri astratti dei Trait
+
+ I Trait supportano l'uso di metodi astratti per imporre requisiti
+ alla classe che li espone. Sono supportati i metodi pubblici, protetti e
+ privati. Prima di PHP 8.0.0, erano supportati solo i metodi astratti
+ pubblici e protetti.
+
+
+
+ A partire da PHP 8.0.0, la firma di un metodo concreto deve seguire le
+ regole di compatibilità della firma.
+ In precedenza, la firma poteva essere diversa.
+
+
+
+ Esprimere requisiti tramite metodi astratti
+
+getWorld();
+ }
+ abstract public function getWorld();
+}
+
+class MyHelloWorld {
+ private $world;
+ use Hello;
+ public function getWorld() {
+ return $this->world;
+ }
+ public function setWorld($val) {
+ $this->world = $val;
+ }
+}
+?>
+]]>
+
+
+
+
+
+ Membri statici dei Trait
+
+ I Trait possono definire variabili statiche, metodi statici e proprietà
+ statiche.
+
+
+
+ A partire da PHP 8.1.0, la chiamata di un metodo statico o l'accesso a una
+ proprietà statica direttamente su un trait è deprecata. I metodi statici e
+ le proprietà statiche devono essere accessibili solo su una classe che usa
+ il trait.
+
+
+
+ Variabili statiche
+
+inc();
+$p = new C2();
+$p->inc();
+
+?>
+]]>
+
+ &example.outputs;
+
+
+
+
+
+ Metodi statici
+
+
+]]>
+
+ &example.outputs;
+
+
+
+
+
+ Proprietà statiche
+
+
+ Prima di PHP 8.3.0, le proprietà statiche definite in un trait erano
+ condivise tra tutte le classi nella stessa gerarchia di ereditarietà che
+ usavano quel trait. A partire da PHP 8.3.0, se una classe figlia usa un
+ trait con una proprietà statica, questa sarà considerata distinta da
+ quella definita nella classe genitore.
+
+
+
+
+]]>
+
+ &example.outputs.83;
+
+
+
+
+
+
+
+ Proprietà
+
+ I Trait possono anche definire proprietà.
+
+
+ Definizione di proprietà
+
+x;
+
+?>
+]]>
+
+
+
+ Se un trait definisce una proprietà, una classe non può definire una
+ proprietà con lo stesso nome a meno che non sia compatibile (stessa
+ visibilità e tipo, modificatore readonly e valore iniziale), altrimenti
+ viene emesso un errore fatale.
+
+
+ Risoluzione dei conflitti
+
+
+]]>
+
+
+
+
+
+ &Constants;
+
+ I Trait possono, a partire da PHP 8.2.0, anche definire costanti.
+
+
+ Definizione di costanti
+
+
+]]>
+
+ &example.outputs;
+
+
+
+
+
+ Se un trait definisce una costante, una classe non può definire una costante
+ con lo stesso nome a meno che non sia compatibile (stessa visibilità, valore
+ iniziale e finalità), altrimenti viene emesso un errore fatale.
+
+
+ Risoluzione dei conflitti
+
+
+]]>
+
+
+
+
+
+ Metodi final
+
+ A partire da PHP 8.3.0, il modificatore final
+ può essere applicato usando l'operatore as
+ ai metodi importati dai trait. Questo può essere usato per impedire alle
+ classi figlie di sovrascrivere il metodo. Tuttavia, la classe che usa il
+ trait può comunque sovrascrivere il metodo.
+
+
+ Definire un metodo proveniente da un trait come final
+
+
+]]>
+
+ &example.outputs.similar;
+
+
+
+
+
+
+
+