Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> agregacja a usuwanie obiektu
dtb
post 15.02.2010, 19:18:07
Post #1





Grupa: Zarejestrowani
Postów: 476
Pomógł: 1
Dołączył: 5.11.2005
Skąd: Bieruń city

Ostrzeżenie: (0%)
-----


mam przykładowo taki kod:
  1. <?php
  2.  
  3. class A {
  4. private $foo;
  5. public function assign($obj) {
  6. $this->foo = $obj;
  7. }
  8. public function __destruct() {
  9. echo "die A\n";
  10. }
  11. }
  12. class B {
  13. public function __destruct() {
  14. echo "die B\n";
  15. }
  16. }
  17.  
  18. $a = new A;
  19. $b = new B;
  20. $a->assign($b);
  21. unset($b);
  22. echo "---\n";
  23.  
  24. ?>

spodziewałem się takiego efektu:
Cytat
die B
---
die A

czyli unset niszczy $b, następnie wyświetlane są "---" i wraz z końcem skryptu usuwany jest obiekt $a.
tymczasem wynik jest taki:
Cytat
---
die A
die B

unset w ogóle nie działa.
może mi ktoś powiedzieć jak usunąć obiekt $b? z góry dziękuje za odpowiedź.

EDIT: $foo musi być prywatna

Ten post edytował dtb 15.02.2010, 19:25:26


--------------------
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 9)
-=Peter=-
post 15.02.2010, 20:05:43
Post #2





Grupa: Zarejestrowani
Postów: 304
Pomógł: 51
Dołączył: 4.02.2005
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Unset usuwa tylko referencję do do zmiennej, a nie samą zmienną. Pamięć jest zwalniana gdy na daną zmienną nie wskazuje już żadna referencja (np. gdy usunięta zostanie ostatnia referencja). W Twoim kodzie istnieje jeszcze referencja do obiektu $b w obiekcie $a i dlatego obiekt $b nie został usunięty (nie wywołał się destruktor).


--------------------
Go to the top of the page
+Quote Post
Pr0100
post 15.02.2010, 21:08:05
Post #3





Grupa: Zarejestrowani
Postów: 114
Pomógł: 24
Dołączył: 18.01.2008
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


  1. <?php
  2.  
  3. class A {
  4. private $foo;
  5. public function assign($obj) {
  6. $this->foo &= $obj;
  7. }
  8. public function __destruct() {
  9. echo "die A\n";
  10. }
  11. }
  12. class B {
  13. public function __destruct() {
  14. echo "die B\n";
  15. }
  16. }
  17.  
  18. $a = new A;
  19. $b = new B;
  20. $a->assign($b);
  21. unset($b);
  22. echo "---\n";
  23.  
  24. ?>


efekt
Kod
die B
---
die A


  1. <?php
  2.  
  3. class A {
  4. private $foo;
  5. public function assign($obj) {
  6. $this->foo = clone $obj;
  7. }
  8. public function __destruct() {
  9. echo "die A\n";
  10. }
  11. }
  12. class B {
  13. public function __destruct() {
  14. echo "die B\n";
  15. }
  16. }
  17.  
  18. $a = new A;
  19. $b = new B;
  20. $a->assign($b);
  21. unset($b);
  22. echo "---\n";
  23.  
  24. ?>


efekt
Kod
die B
---
die A
die B


--------------------
Go to the top of the page
+Quote Post
LBO
post 15.02.2010, 21:40:26
Post #4





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


-=Peter=- wyjaśnił dlaczego dzieje się tak, a nie inaczej.
Pr0100 wyjaśnił jak można to obejść.

Ja od siebie dodam kod, który to zobrazuje istotę problemu.
  1. class A {
  2. private $b;
  3.  
  4. public function setB(B $b) {
  5. $this->b = $b;
  6. }
  7.  
  8. public function unsetB() {
  9. unset($this->b);
  10. }
  11.  
  12. public function __destruct() {
  13. echo __METHOD__ . PHP_EOL;
  14. }
  15. }
  16.  
  17. class B {
  18. public function __destruct() {
  19. echo __METHOD__ . PHP_EOL;
  20. }
  21. }
  22.  
  23. $a = new A;
  24. $b = new B;
  25. $a->setB($b);
  26. $a->unsetB(); // usuwasz $b w obiekcie $a, zostało jeszcze "globalne" $b (użyłem ", bo to nie jest oczywiście prawdziwie globalna zmienna).
  27.  
  28. unset($b); // usuwasz "globalne" $b , nie ma już nigdzie $b . Destruktor B się wykona.
  29. // w przykładzie Pr0100 istnieje tylko "globalne" $b
  30.  
  31. echo "---" . PHP_EOL;


Wynik:
Cytat
B::__destruct
---
A::__destruct


Zostaje nadal problem samych destruktorów i czy warto ich używać. Kilka miesięcy temu, ktoś poruszył podobny temat i tutaj masz link do tych kilku zdań, które wtedy napisałem.
Go to the top of the page
+Quote Post
dtb
post 16.02.2010, 19:01:12
Post #5





Grupa: Zarejestrowani
Postów: 476
Pomógł: 1
Dołączył: 5.11.2005
Skąd: Bieruń city

Ostrzeżenie: (0%)
-----


klonowanie, ani rozwiązanie LBO absolutnie nie wchodzi w grę.
LBO: destruktorów tu użyłem jedynie do debugowania i aby zobrazować problem.
dzięki pr0100: próbowałem wcześniej z =&, a miało być &=.


--------------------
Go to the top of the page
+Quote Post
zegarek84
post 16.02.2010, 21:05:19
Post #6





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


Cytat(dtb @ 16.02.2010, 19:01:12 ) *
dzięki pr0100: próbowałem wcześniej z =&, a miało być &=.

muszę Cię jednak rozczarować winksmiley.jpg - włącz sobie raportowanie błędów winksmiley.jpg
$a &= $b
oznacza
$a = $a & $b

unset usuwa tutaj tylko referencję - obiekt jest niczszony po zniszczeniu ostatniej możliwej referencji... i tu swoją drogą logikę jaką chcesz uzyskać jest dla mnie troszku nie zrozumiała - skoro obiekt A potrzebuje obiektu B to obiekt B powinien zostać zniszczony na końcu tak jak się to dzieje - a w php 5 każdy obiekt domyślnie jest przekazywany przez referencję... jest sposób na obejście tego ale do sklepu się śpieszę - jak wrócę pomyślę winksmiley.jpg (no clon - czyli inny obiekt Cię nie interesuje ^^)

Ten post edytował zegarek84 16.02.2010, 21:10:38


--------------------
Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.

Go to the top of the page
+Quote Post
dtb
post 21.02.2010, 19:38:15
Post #7





Grupa: Zarejestrowani
Postów: 476
Pomógł: 1
Dołączył: 5.11.2005
Skąd: Bieruń city

Ostrzeżenie: (0%)
-----


nigdzie nie powiedziałem, że obiekt A potrzebuje B. wręcz przeciwnie. w moim projekcie A (nazwijmy go WINDOW) i B (BUTTON) są widgetami. BUTTON samodzielnie nie może być wyświetlony, potrzebuje do tego WINDOW, który wyświetli widgety na nim. chodzi o to, by można było np. usunąć BUTTON - wtedy destruktor wyśle informacje do klienta (ajax), aby usunąć widget. rozwiązanie LBO jest nieintuicyjne i niewygodne w przypadku bardziej rozbudowanej hierarchii, jak np. WINDOW > TABLE > TOOLBAR > BUTTON.
warto wspomnieć, że nazwa zmiennej, jest jednocześnie unikalnym id widgetu przez który się odwołuje do niego. czyli nie:
$window1->table1->toolbar1->button1, tylko samo $button1.

zdziwiło mnie rozwiązanie z &=, ale działa tak jak oczekiwałem.

Ten post edytował dtb 21.02.2010, 19:39:24


--------------------
Go to the top of the page
+Quote Post
LBO
post 22.02.2010, 00:27:21
Post #8





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Już drugi raz wyskakuje mój nick, dlatego, czy mogę się zapytać Ciebie @dtb, co dokładnie uważasz za moje rozwiązanie?

1. Mój poglądowy kod? Bo to nie miało służyć jako żadne rozwiązanie, tylko wyjaśnić problem. Cytuję: "Ja od siebie dodam kod, który to zobrazuje istotę problemu.".
Dam coś prostszego:

  1. class A {
  2. public function __destruct() { echo __METHOD__ . PHP_EOL;}
  3. }
  4.  
  5. $a1 = new A;
  6. $a2 = $a1;
  7. unset($a1); // destruktor się nie wykona, bo istnieje jeszcze $a2
  8. print '---' . PHP_EOL;


2. Koncepcję z linku który podałem? Bo w życiu nie nazwałbym go nieintuicyjnym, ani niewygodnym. Szczerze? Nie wyobrażam sobie, abyś nie użył analogicznego rozwiązania do Twojego WINDOW > TABLE > TOOLBAR > BUTTON.
Go to the top of the page
+Quote Post
dtb
post 22.02.2010, 01:02:43
Post #9





Grupa: Zarejestrowani
Postów: 476
Pomógł: 1
Dołączył: 5.11.2005
Skąd: Bieruń city

Ostrzeżenie: (0%)
-----


ech... niepotrzebnie zaczynałem dyskusję.

przyczepiłem się tego, bo myślałem, że to proponowane przez Ciebie rozwiązanie (mój błąd - źle przeczytałem):
Kod
$a->unsetB();
unset($b);

takie rozwiązanie oczywiście nie pasuje, bo załóżmy że mam więcej obiektów wrzuconych do $a:
Kod
$a->assign($button1 = new B);
$a->assign($button2 = new B);
$a->assign($button3 = new B);
$a->assign($foo = new B);

ich liczba nie jest określona. jak bym chciał usunąć obiekt $button3, to nie mogę przecież utworzyć metody unsetButton3 (i tak dla każdej potencjalnej nazwy zmiennej). to było by bez sensu.

natomiast zaproponowany przez ciebie system zarządzania obiektami nie jest rozwiązaniem jakiego oczekuje, ponieważ nie chodzi mi o kolejność wykonywania destruktorów, a jedynie o możliwość usunięcia pojedynczej instancji wraz z wszystkimi jej referencjami w dowolnym miejscu w kodzie. widać źle zrozumiałeś moje intencje na samym początku.

Ten post edytował dtb 22.02.2010, 01:19:15


--------------------
Go to the top of the page
+Quote Post
LBO
post 22.02.2010, 02:25:16
Post #10





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(dtb @ 22.02.2010, 01:02:43 ) *
[...] ich liczba nie jest określona. jak bym chciał usunąć obiekt $button3, to nie mogę przecież utworzyć metody unsetButton3 (i tak dla każdej potencjalnej nazwy zmiennej). to było by bez sensu. [...]

Masz kilka opcji:

1. Bawisz się w klonowanie. Wtedy zużycie pamięci może skoczyć pod sufit, a to może boleć.

2. &= naprawdę nie działa. Zdebuguj to sobie dokładnie.

3. Bawisz się rozwiązaniem z linku. Nie ma ono za zadanie tylko zastępować destruktorów, ono ma zarządzać obiektami. Wymaga to więcej pracy i planowania, ale jest do zrobienia.
  1. $a->assign($button1 = new B);

Nie powinno być:
  1. $a->assign('button1', new B);

Cytat(dtb @ 22.02.2010, 01:02:43 ) *
[...] to było by bez sensu.


Nie, jak będziesz miał coś w stylu:
  1. $a->remove('button1');


Wszystko rozbija się o abstrakcję.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 24.07.2025 - 17:03