Επίλυση συγκρούσεων μεθόδων traits στο αντικειμενοστραφή προγραμματισμό στην PHP
Εφόσον μια κλάση μπορεί να χρησιμοποιήσει πολλά traits, μπορεί να αντιμετωπίσουμε ένα πρόβλημα που προκύπτει όταν δύο traits έχουν μεθόδους με το ίδιο όνομα.
Σε αυτή την περίπτωση η PHP θα εμφανίσει ένα μοιραίο σφάλμα. Για να διορθώσουμε την κατάσταση, θα χρειαστεί να επιλύσουμε τη σύγκρουση ονομάτων ρητά. Πώς γίνεται αυτό - θα το δούμε στην πράξη.
Ας υποθέσουμε ότι έχουμε δύο traits με την ίδια
μέθοδο method:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
Ας υποθέσουμε επίσης ότι έχουμε μια κλάση Test,
που χρησιμοποιεί και τα δύο traits μας. Αν απλά
συνδέσουμε και τα δύο traits στην κλάση μας, τότε
η PHP θα εμφανίσει σφάλμα, καθώς τα traits έχουν
μεθόδους που συμπίπτουν:
<?php
// Αυτός ο κώδικας θα εμφανίσει σφάλμα!
class Test
{
use Trait1, Trait2; // συνδέουμε τα traits
}
?>
Ας επιλύσουμε τη σύγκρουση ονομάτων
των traits μας. Για αυτό υπάρχει ένας ειδικός
τελεστής insteadof. Με αυτόν τον τελεστή
θα χρησιμοποιήσουμε τη μέθοδο method του trait
Trait1 αντί για την ίδια μέθοδο του trait
Trait2:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
Όπως βλέπετε, η σύνταξη εδώ είναι η εξής: πρώτα
το όνομα του trait, μετά δύο άνω και κάτω τελείες, μετά το όνομα
της μεθόδου, μετά ο τελεστής μας insteadof
και το όνομα του δεύτερου trait.
Ας ελέγξουμε:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // θα εμφανίσει 1, αφού αυτή είναι η μέθοδος του πρώτου trait
}
}
new Test;
?>
Έτσι, στην κλάση μας είπαμε ότι αν
χρησιμοποιείται η μέθοδος method, τότε θα
πρέπει να λαμβάνεται από το πρώτο trait. Μπορούμε και αντίστροφα
- να πάρουμε τη μέθοδο του δεύτερου trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // θα εμφανίσει 2, αφού αυτή είναι η μέθοδος του δεύτερου trait
}
}
new Test;
?>
Σε κάθε περίπτωση, αν υποδείξουμε να χρησιμοποιηθεί
η μέθοδος ενός trait, τότε η μέθοδος του δεύτερου trait
γίνεται μη διαθέσιμη. Μπορούμε να χρησιμοποιήσουμε
και τη μέθοδο του δεύτερου trait, μετονομάζοντάς την
μέσω της λέξης-κλειδιού as, ως εξής:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // θα εμφανίσει 3
}
}
new Test;
?>
Αν θέλουμε, μπορούμε να μετονομάσουμε και τη μέθοδο του πρώτου trait:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2(); // θα εμφανίσει 3
}
}
new Test;
?>
Δεν μπορούμε να χρησιμοποιήσουμε τη λέξη-κλειδί as χωρίς
τον ορισμό της κύριας μεθόδου μέσω insteadof,
αυτό θα εμφανίσει σφάλμα:
<?php
// Αυτή η κλάση θα εμφανίσει σφάλμα:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Δημιουργήστε 3 traits με ονόματα Trait1,
Trait2 και Trait3. Ας υπάρχει στο πρώτο
trait μια μέθοδος method, που επιστρέφει
1, στο δεύτερο trait - μια ομώνυμη
μέθοδος, που επιστρέφει 2, και στο τρίτο
trait - μια ομώνυμη μέθοδο,
που επιστρέφει 3.
Δημιουργήστε μια κλάση Test, που χρησιμοποιεί
και τα τρία traits που δημιουργήσαμε. Δημιουργήστε σε
αυτήν την κλάση μια μέθοδο getSum, που επιστρέφει
το άθροισμα των αποτελεσμάτων των μεθόδων των συνδεδεμένων traits.