Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dynamiczne dodawanie właściwości do obiektu
Forum PHP.pl > Forum > PHP > Object-oriented programming
nevt
witajcie, może jestem durny, ale przewaliłem manual we wszystkie strony i nie znalazłem uzasadnienia do poprawności poniższej konstrukcji w PHP5, a jednak ona działa:

  1. <?php
  2. class x{};
  3. $x = new x();
  4. $x->test = 'dlaczego to tworzy nową właściwość w klasie?';
  5. echo $x->test;
  6. echo '<br />';
  7. ?>

a jeżeli to jest z jakichś dziwnych powodów normalne w PHP - to czy można jakoś ten mechanizm wyłączyć... questionmark.gif
LBO
  1. <?php
  2. class x
  3. {
  4.    public function __set($name, $value)
  5.    {
  6.        trigger_error('cannot set undefined property');
  7.    }
  8. };
  9. ?>
nevt
heh - dzięki - to że mogę zablokować __set to wiem... ale chodzi mi o globalne rozwiązanie... przecież bez sensu jest dopisywać tą funkcję do wszystkich klas w projekcie. jestem po prostu totalnie zaskoczony i rozczarowany, że pehap dopuszcza taka kombinację. to śmiech z podstaw OOP...
LBO
Ach, to przepraszam sad.gif

Na pocieszenie pokażę ci to:

  1. <?php
  2.  
  3. //error_reporting(E_ALL | E_STRICT);
  4. //ini_set('display_startup_errors', 1);
  5. //ini_set('display_errors', 1);
  6.  
  7. $foo->bar = "jestem obiektem powstałym z niczego";
  8. var_dump($foo);
  9.  
  10. ?>


biggrin.gif:D:D:D:D

edit:

Ha, znalazłem.
Cytat
It’s not a bug, it’s a feature!
mike
Nie rozumiem poruszenia. Od zawsze tak było i nie ma w tym nic strasznego.
sobstel
Wydaje mi się, że to zachowanie jest całkowicie normalne dla PHP jako języka, w którym nie trzeba deklarować zmiennych wprost etc. I skoro to samo odnosi się do zmiennych, więc naturalne jest, że tak samo działa dla właściwości obiektu. W obu przypadkach PHP wyrzuca też błędy E_NOTICE (odpowiednio Undefined variable i Undefined property), co należy interpretować tak, że "pozwalamy tak robić, ale nie polecamy".

Co do przykładu LBO, to rzeczywiście takie zachowanie wydaje się trochę dziwne, ale chyba zostało pozostawione bardziej ze względu backward compatibilty, skoro obecnie w php5 wyrzuca Strict standards: Creating default object from empty value.
LBO
notice wyrzuca tylko kiedy chcesz odczytać atrybut wcześniej nie ustawiony. Czyli jak ustawisz taki, który nie występował w deklaracji klasy, a potem go odczytasz to nic nie wyskoczy.
sobstel
Cytat(LBO @ 11.11.2008, 18:35:21 ) *
notice wyrzuca tylko kiedy chcesz odczytać atrybut wcześniej nie ustawiony. Czyli jak ustawisz taki, który nie występował w deklaracji klasy, a potem go odczytasz to nic nie wyskoczy.


Dokładnie tak jak w przypadku zmiennych, od czego zacząłem mojego posta. Jest to dla mnie naturalne zachowanie dla PHP. Nie chcę tu za wszelką cenę tego bronić i nie wiadomo czego udawadniać, ale podobnie jak mike nie widzę tutaj nic strasznego.
nevt
ok. przyjmuję do wiadomości, że skoro zawsze tak było, to trudno, już zawsze tak będzie.

może i nic w tym strasznego, ale logiki jednak brak.

chociażby dlatego, że może skutkować ciężkimi do wychwycenia błędami w przypadku prostych literówek w nazwach właściwości obiektu. dla mnie zmienna prosta w kodzie programu a właściwość obiektu to nie to samo.

gdyby tak podchodzić do wszystkich kwestii to po co OOP w PHP ? po co PHP5 a teraz 6 skoro stare, poczciwe 4 nadal świetnie się spisuje?

pozdrawiam.
mike
Cytat(nevt @ 11.11.2008, 23:17:01 ) *
może i nic w tym strasznego, ale logiki jednak brak.
No własnie jest w tym logika. ~sobstel ładnie to wytłumaczył.
Cytat(nevt @ 11.11.2008, 23:17:01 ) *
chociażby dlatego, że może skutkować ciężkimi do wychwycenia błędami w przypadku prostych literówek w nazwach właściwości obiektu
Stosowanie pól publicznych i jawne odwołania do nich to powinna być rzadkość.
Więc potencjlny błąd możesz popełnić bardzo rzadko.
dr_bonzo
Cytat
chociażby dlatego, że może skutkować ciężkimi do wychwycenia błędami w przypadku prostych literówek w nazwach właściwości obiektu. dla mnie zmienna prosta w kodzie programu a właściwość obiektu to nie to samo.

Jak wyzej - publiczne pola?questionmark.gif (normalnie nie uzywam, oprocz w moim ORM - dla wygody)
Pozatym masz uzupelnianie skladni wiec gdzie miejsce na bledy
nevt
Cytat
Stosowanie pól publicznych i jawne odwołania do nich to powinna być rzadkość.
Więc potencjlny błąd możesz popełnić bardzo rzadko.

a czy ja gdzieś napisałem o publicznych właściwościach... questionmark.gif
przecież w kodzie klasy bez przerwy są odwołania do jej właściwości... to właśnie dlatego się wkurzyłem na tą konstrukcję bo kilka godzin straciłem na oświecenie że przy literówce w stylu:
  1. <?php
  2. class test
  3. {
  4.  private $dlugaNazwaZmiennej = 'TEST';
  5.  
  6.    public function __construct($value)
  7.    {
  8.        $this->dlugaNawzaZmiennej = $value;
  9.    }
  10.    
  11.    public function get()
  12.    {
  13.        return $this->dlugaNazwaZmiennej;
  14.    }
  15. }
  16.  
  17. $test = new test('ZMIANA');
  18. echo $test->get();
  19. ?>

nie dostaję od PHP najmniejszej uwagi czy ostrzeżenia...

a co do logiki to mnie nie przekonacie. nie można stawiać znaku równości między zmienną strukturalną i właściwością obiektu. to zachowanie php narusza jedną z podstawowych zasad OOP czyli hermetyzację. przecież user sobie może wrzucać do dowolnej klasy dowolne dane, na których metody obiektu nie wykonują żadnych operacji. nie mam pretensji że tak jest - tak to sobie autorzy PHP wymyślili i trudno - dostosuję się - ale nie wciskajcie mi, że jest to normalne i logiczne zachowanie kodu przy OOP... i na pewno niczego nie ułatwia a tylko potencjalnie komplikuje debugowanie aplikacji.

proponuję zakończyć dyskusję, pozdrawiam wszystkich.
Cysiaczek
Heh, no można się o to spierać, ale ten bug...eee...feature nie stoi w sprzeczności z OOP - jest raczej zaburzeniem samego języka wynikającym z jego filozofii. Wydaje mi się, że twórcy podeszli do tego jak do normalnych zmiennych, czyli
  1. <?php
  2. $foo=true;
  3. $o->foo=true;
  4. ?>

Oznaczają to samo - inicjalizację zmiennej i jednoczesne przypisanie jej typu i wartości. Zauważcie, że intencja wydaje się słuszna - mniej pisania - lżejszy kod.
  1. <?php
  2. class A{}
  3. $o=new A();
  4. $o->foo=true;
  5. // jest lżejsze niż
  6. class A
  7. {
  8.  var foo;
  9. }
  10. $o=new A();
  11. $o->foo=true;
  12. ?>

Specjalnie użyłem var, bo taka była filozofia wcześniejszych wersji PHP. Skoro php5 jest kompatybilne z 4, to taka konstrukcja jest jak najbardziej poprawna. Skrypty PHP miały być szybkie, mało zajmować na dysku i pochłaniać mało pamięci. Jak to wygląda dla interpretera? Czy jeśli nie tworzy składowej na starcie, to oszczędza trochę pamięci? (nie zawsze trzeba z tej zmiennej korzystać)

Pozdrawiam
ucho
Dla mnie nielogiczne jest
Kod
<?php
$a = array(1,2);
foreach($a as &$i) {
}
foreach($a as $i) {
}
print_r($a);

I to, że w manualu jest opisane dlaczego się tak dzieje i jak sobie z tym radzić wcale mnie nie przekonuje - podobnie jak w powszechnie znanym:
Kod
<?
var_dump(0 == '');
var_dump(0 == '0');
var_dump('' == '0');

A możliwość takiego modyfikacji obiektów jak opisana wątku to cecha powszechna wśród wszystkich języków dynamicznych.
singollo
Cytat(ucho @ 13.11.2008, 09:06:23 ) *
I to, że w manualu jest opisane dlaczego się tak dzieje i jak sobie z tym radzić wcale mnie nie przekonuje - podobnie jak w powszechnie znanym:
Kod
<?
var_dump(0 == '');
var_dump(0 == '0');
var_dump('' == '0');

A możliwość takiego modyfikacji obiektów jak opisana wątku to cecha powszechna wśród wszystkich języków dynamicznych.


Ale jeśli się zastanowisz przez chwilę, to bool(false) w trzecim przykładzie jest oczywiste. W innym wypadku porównanie dwóch danych przesłanych przez użytkownika (wszystko z POST, GET itp to string) byłoby, co najmniej, zawodne - zwłaszcza przed wprowadzeniem operatora ===
ucho
Ale psuje się przechodniość, nawet kiedy "==" oznacza "równe, choć nie musi mieć tego samego typu" to było by miło gdyby
  1. <?php
  2. (a==b) && (a==c) => b==c
  3. ?>

Efekt jest taki że w łaściwie z == nie powinno się korzystać tylko wszystko ręcznie rzutować na określony typ i porównywać ===. Tylko wtedy do czego nam == potrzebne ?
Ogólnie to tylko takie moje narzekanie bo wiadomo, że tak było, jest i będzie w dającej się przewidzieć przyszłości, choćby ze względu na zgodność ze starszym oprogramowaniem. W sumie chyba lepsze podejście niż "Chodźcie zmienimy print z instrukcji na funkcję, nieważne że wszystko się posypie, zrobimy jakieś automaty które _prawie_ wszystko przerobią same" w pythonie3k =)
bregovic
Jeśli wiesz co robisz, to czasem == można użyć z dużą efektywnością. Słabe typowanie PHP jest jednocześnie pięknem i stopą achillesową PHP. Co do tematu, to wydaje mi się że ta konstrukcja pochodzi jeszcze z czasów gdy obiekty w PHP były rozszerzonymi tablicami, a w tablicach jak wiadomo można definiować wartości bez żadnych ceregieli. Niestety PHP w tej chwili znajduje się raczej w niezbyt eksperymentalnym okresie, i jakakolwiek propozycja złamania BC (poza najmniejszymi) wywołuje w devach napady padaczki (przynajmniej wnioskując z @internals).
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.