Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Instance w klasie extended
Forum PHP.pl > Forum > Przedszkole
-JacekP-
Witam

Mam pytanie, jak rozwiązać sprawę $_instance w klasie rodzica ?
Stworzyłem znaną wszystkim funkcję :

<code=php> private static $_instance;

public static function instance() {

if(!isset(self::$_instance)){
self::$_instance = new static();
}
return self::$_instance;
}</code>
Teraz każda klasa która dzedziczy po tej klasie ma funkcję instance, problem jednak pojawił się taki że $_instance przyjmuje wartość pierwszej stworzonej klasy którą zainicjuję tą funkcją, wydaje mi się to błędnym działaniem, zmienna $_instance mimo że statyczna powinna być statyczną dla klasy która dziedziczy po tej,

Jak rozwiązać ten problem, czy mogę usunąć static, wtedy będą się za każdym razem tworzyć się nowe kopie dla każdej klasy i funkcja straci sens :/

Crozin
Po pierwsze $_instance jest oznaczona jako private, więc w klasach potomnych nie będzie nawet istnieć. Po drugie powinieneś zainteresować się late static bindings, bo w teorii to jest rozwiązanie Twojego problemu. Po trzecie i najważniejsze: czy Ty w ogóle potrzebujesz używać tu czegokolwiek statycznego, a tym bardziej Singletona? Jakiś konkretny powód by z niego skorzystać?
-JacekP-
Przejrzałem wątek, i nie znajduję tam rozwiązania, problem jest taki że nie ma jak utworzyć zmiennej statycznej ale dla jednego rodzaju klasy, czy takie coś jest możliwe ?
Bo dla mnie klasa B i C to 2 zupełnie inne klasy, więc powinna istnieć możliwość przypisania im różnych wartości $me.

  1. <?php
  2. class A
  3. {
  4.  
  5. public static $me;
  6.  
  7. public static function getInstance()
  8. {
  9. if(!isset(self::$me)){
  10. self::$me = new static();
  11. }
  12. return self::$me;
  13. }
  14.  
  15. }
  16.  
  17. class B extends A
  18. {
  19. //stuff...
  20. }
  21. class C extends A
  22. {
  23. //stuff...
  24. }
  25.  
  26. $obj1 = B::getInstance();
  27. $obj2 = C::getInstance();
  28. echo get_class($obj1).' -- '.get_class($obj2); // B -- B, czemu nie B -- C, czy taki efekt da się uzyskać ?
  29.  
  30.  
  31. ?>


Jeśli chodzi o to po co mi to, to mam dużo klas które muszą być dostępne z dowolnego miejsca w kodzie np. klasa która zbiera logi.
konrados
Też miałem ten problem w związku z tym, że trochę za dużo lat spędziłem nad c++. Tam domyślnie klasa rodzic widzi tylko zmienne i funkcje zdefiniowane tylko w tejże klasie (wyjątkiem są zdefiniowane explicitly jako funkcje wirtualne).

Dużo czasu minęło zanim naumiałem się filozofii php - tu w klasie rodzica masz domyślnie dostęp do zmiennych i funkcji zdefiniowanych w klasie dziecka. Właśnie dlatego ci co znają tylko php mogą mieć problem ze zrozumieniem Twojego pytania i jego sensu. Spójrz na to:
  1. <?php
  2. class rodzic {
  3. public function test(){
  4. echo $this->zmienna;
  5. }
  6. }
  7.  
  8. class dziecko extends rodzic{
  9. function __construct(){
  10. $this->zmienna = 'kaczka';
  11. }
  12. }
  13.  
  14. $dziecko = new dziecko;
  15. $dziecko->test();


Wypluje 'kaczka', rozumiesz? Twój singleton może spokojnie zwracać instancję klasy rodzica i to jest ok w php.
-JacekP-
Zauważ jednak że przenosisz zmienną z rodzica do dziecka, w takim wypadku można sobie darować całą funkcję getInstance i przenieść po prostu do dzieci, ale nie o takie rozwiązanie mi chodziło. wink.gif
konrados
No dobra, to może inaczej: jeszcze się szczerze mówiąc w żadnym projekcie nie spotkałem z dziedziczeniem po klasie, która w założeniu ma być singletonem.

Singletony (w założeniu) raczej służą jako zastępstwo dla namespace i funkcji statycznych, dając jednocześnie dodatkowe zalety.

Możesz powiedzieć po pierwsze, po co Ci singleton, po drugie, czemu chcesz z niego dziedziczyć? Bo ciekaw jestem:)
Crozin
Cytat
Jeśli chodzi o to po co mi to, to mam dużo klas które muszą być dostępne z dowolnego miejsca w kodzie np. klasa która zbiera logi.
No to obiekt zbierający logi to świetny przykład tego, że użycie Singletona będzie błędem. Już dużo lepszym rozwiązaniem będzie skorzystanie z normalnego globala.
Google: Dependency Injection oraz Dependency Injection Container - od dekad* znane, dobre rozwiązanie Twojego problemu. A Singletona nie używa się tam gdzie potrzebujesz globalnego dostępu do czegoś.
-JacekP-
Dzięki za zainteresowanie.

Cytat
Możesz powiedzieć po pierwsze, po co Ci singleton, po drugie, czemu chcesz z niego dziedziczyć? Bo ciekaw jestem:)

A ot mam 4 klasy które okazały się niezbędne w różnych "sekcjach" aplikacji, właśnie log, czy klasa User etc.
Zwyczajnie musiałem przeklejać kod więc pomyślałem że zrobię klasę która będzie posiadać getInstance i z niej inne będą dziedziczyć. Wydało mi się to eleganckie, bo jak inaczej mam pobrać klasę która jest gdzieś tam tworzona.

Albo musiał bym do każdej głupiej klasy ładować referencję do niej, a tak miałem prosty kod Log->me()->msg('coś tam coś');

Jak rozumiem ten prosty kod jest nie zalecany, w sumie trochę to zaprzecza obiektowości, tak przynajmniej na moje oko.
Podobnie global też jest dla mnie jakimś nie porozumieniem, to po kiego bawić się w klasy.


Skoro zalecacie zrezygnować z sigletona to może sensowne jednak będzie stworzyć 4 klas głównych dla każdej sekcji i do każdej z nich skierować referencję głównej klasay gdzie już by gotowe instancje klas istniały czli:


  1. <?php
  2. class Starter
  3. {
  4.  
  5. public $sekcja1;
  6. public $sekcja2;
  7. public $sekcja3;
  8. public $sekcja4;
  9.  
  10. public FUNCTION run()
  11. {
  12. //stworz stronę
  13. }
  14.  
  15.  
  16. }
  17.  
  18. $s = new Starter();
  19. $s->addSekcje1($s);
  20. //etc...
  21. $s->run();
  22.  
  23.  
  24.  
  25. ?>


W takiej konfiguracji w razie czego główne klasy miały by dostęp do wszystkich danych.

?
Crozin
Cytat
Wydało mi się to eleganckie, bo jak inaczej mam pobrać klasę która jest gdzieś tam tworzona.
Zawsze powinieneś dążyć do tego by przekazywanie zależności było jawne, najlepiej na podstawie interfejsu, nie klasy (oczywiście tam gdzie to ma sens).
Cytat
Albo musiał bym do każdej głupiej klasy ładować referencję do niej, a tak miałem prosty kod Log->me()->msg('coś tam coś');
Ten kod jest tak ładny, że przy pierwszej próbie modyfikacji, wymiany implementacji, przetestowania aplikacji czy ponownego użycia kodu przez dwa dni klnąłbyś pod nosem. A jakbyś miał jeszcze kilka aplikacji do zmodyfikowania trwałe samookaleczenie wydałoby Ci się znacznie lepszą alternatywą.
Cytat
Jak rozumiem ten prosty kod jest nie zalecany, w sumie trochę to zaprzecza obiektowości, tak przynajmniej na moje oko.
W obiektowości chodzi o rozwiązywanie problemów na poziomie obiektów, nie klas.
Cytat
Podobnie global też jest dla mnie jakimś nie porozumieniem, to po kiego bawić się w klasy.
A co Ty zrobiłeś jak nie "ładną otoczkę" dla zwykłego globala? Zwykły global mimo iż jest złem wcielonym, jest jeszcze o tyle lepszy, że nadal pozostawia możliwość chociażby wymiany implementacji.

Zanim zaczniesz jeszcze wymyślać swoje rozwiązania (swoją drogą nie do końca zrozumiałem jak chciałbyś by ten Starter działał) skorzystaj może najpierw ze sprawdzonych rozwiązań? Patrz, mój wcześniejszy post, dot. DIC-a.
-JacekP-
Nie do końca rozumiem jak by ten DIC miał działać. Przeglądam googla i poczytuje.

Mam powiedzmy jedną klasę, i 2 moduły, log i user , a więc DIC działa tak że tworzę klasę Dic , w niej tworzę klasy modułów czli log i user, potem w klasach gdzie potrzebne jest np. zapisanie info do loga to odpalam

  1. $log = $dic->get('log');
  2. $log->dosomthing();
  3. $log->dosomthingelse();


Pytanie tylko jak do klasy w której potrzebny jest log przekazać Dic a ?
Czy poprzez wkładanie za każdym przez jakąś funkcję czy konstruktor ?

  1. //1
  2. $staff = new Staff(dic);
  3. //or
  4. $staff->addDic(dic);


Czy tak działa idea DIC ? Przyznam że nie do końca rozumiem jak powinienem przekazywać DICa.
Tutaj widzę że ktoś rozkminiał http://forum.php.pl/index.php?showtopic=157036 ale ostatecznie tylko został zjechany a odpowiedzi nie ma.

Prosił bym o jakąś wskazówkę, bo w 1 kolejności myślałem o takim przekazywaniu ale wydawało mi się że z czasem może dojść do mega gmatwaniny, być może jednak jest to tylko pozorne wrażenie.

pzdr
-JacekP-
? to naprawdę popularny problem, prosił bym o jakąś odpowiedz.

pzdr
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.