PHP – co robić gdy potrzeba coś przeciążyć?

Jednym z najbardziej dla mnie niekomfortowych żeczy w PHPe jest brak możliwości przeciążania czy to funkcji czy też metod w kontekście OO.  Jak wiadomo związane jest to z brakiem m.in. ścisłej kontroli typów. No cóż rzeczywistość jest jaka jest i trzeba do niej się dostosować. Najczęściej pojawiającym się zabiegiem w celu implementacji „przeciążania” metod jest użycie magicznych metod. Sposób takiej implementacji można podejrzeć w wpisie „Method Overloading in PHP5” na blogu Caught in a Web. Osobiście nie przepadam za tego rodzaju rozwiązaniami. Tak więc w wolnym czasie zacząłem główkować i kombinować jak to można by był zrobić troszkę inaczej. Z przemyśleń narodził się pomysł aby do „przeciążania”  (pseudo przeciążania) wykorzystać namespace (opis dostępny w manualu PHP oraz na stronie z poradnikami IBMa „Create better namespaces in PHP”). Pomysł bazuje na prostych zasadach:

– wykorzystaniu  bazowej przestrzeni nazw dla metod podstawowych które będą przeciążane, zaimplementowane lub nadpisane w klasach potomnych. Najlepiej wykorzystać abstrakcje,

– wykorzystaniu predefiniowanych przestrzeni nazw  do enkapsulacji przeciążanych klas i ich metod,

– zamknięcie przestrzeni bazowej i predefiniowanej w jednym pliku (daje to swego rodzaju konwencję utrzymania kodu i jego standaryzację w obrębie realizowanego projektu). Ewentualnie można odpowiednio sobie porozbijać klasy na pliki. Opisu tego rozwiązania jednak nie dokonałem i jedynie skupiłem się na podstawowej strukturze – jeden plik.

Przykładową implementację całości rozwiązania bazującego na ww. zasadach przedstawiłem poniżej. Miłego czytania i zapoznawanie się z pomysłem. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!--?php
 
// Converter.php
 
/**
 * Bazowa (podstawowa) przestrzeń nazw
 *
 * @author Marcin M.
 *
 */
namespace BaseNamespace {
 
    /**
     * Abstrakcyjna klasa konwertera
     *
     * @author Marcin M.
     *
     */
    abstract class Converter {
        abstract public function convert($arg1);
    }
 
}
 
/**
 * Przestrzeń nazw dla konwertera `String`
 *
 * @author Marcin M.
 *
 */
namespace StringNamespace {
 
    use BaseNamespace;
 
    class Converter extends BaseNamespace\Converter {
        public function convert($arg1) {
            return (string) $arg1;
        }
    }
 
}
 
/**
 * Przestrzeń nazw dla konwertera `Float`
 *
 * @author Marcin M.
 *
 */
namespace FloatNamespace {
 
    use BaseNamespace;
      
    class Converter extends BaseNamespace\Converter {
        public function convert($arg1) {
            return (float) $arg1;
        }
    }
}
 
/**
 * Przestrzeń nazw aplikacji
 *
 * @author Marcin M.
 *
 */
namespace {
 
    use StringNamespace as String;
    use FloatNamespace as Float;
     
    $stringConverter = new String\Converter();
    $floatConverter = new Float\Converter();
     
    echo 'Konwersja na string ' . $stringConverter--->convert('123');
    echo "\n";
    echo 'Konwersja na float ' . $floatConverter->convert('123.12');
}
 
?>

Oczywiście przedstawiona metoda w żaden sposób nie zastępuje klasycznego przeciążania i wywoływania z obiektu metody w zależności od kontekstu (specyfikacji jej deskryptora). Niemniej stanowi pewne obejście za pomocą którego można zdefiniować jawnie o jaki typ konwersji nam chodzi. Użytkownik (programista) musi sam jawnie w kodzie zadeklarować, w tym przypadku, na jaki typ ma się odbyć konwersja. W pewien sposób poprawia to czytelność kodu i nie musimy dochodzić do tego co gdzie i jak zostało prze-konwertowane dynamicznie przez kompilator/interpreter w przypadku klasycznego przeciążania. Z drugiej strony pociąga to dodatkowy narzut na projektowanie elastycznej i jasnej konwencji przestrzeni nazw. Tak więc jak to w programowaniu i nie tylko w nim bywa, są ciemne jak i jasne strony stosowania pewnych rozwiązań. Zachęcam do eksperymentów i powodzenia.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Ta strona używa Akismet do redukcji spamu. Dowiedz się, w jaki sposób przetwarzane są dane Twoich komentarzy.