Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Porównywanie obiektów - Dziwne
mstraczkowski
post
Post #1





Grupa: Zarejestrowani
Postów: 273
Pomógł: 52
Dołączył: 3.02.2013
Skąd: Przemyśl

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


Testując sobie mój własny moduł do walidacji natknąłem się na pewien problem, którego nie potrafię wyjaśnić.
Albo ja jestem przemęczony, albo PHP świruje i to kolejne z jego "FUCK LOGIC"
Może ktoś wie co jest grane i o co może chodzić ?

Mianowicie chodzi o porównywanie obiektów, w dokumentacji możemy przeczytać:

Cytat
Comparing Objects

In PHP 5, object comparison is more complicated than in PHP 4 and more in accordance to what one will expect from an Object Oriented Language (not that PHP 5 is such a language).

When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class.


Na prostym przykładzie możemy zobaczyć zachowanie tej zależności

  1. class A
  2. {
  3. protected $property;
  4.  
  5. public function __construct($value)
  6. {
  7. $this->property = $value;
  8. }
  9. }
  10.  
  11. $object1 = new A('ABC');
  12. $object2 = new A('XYZ');
  13.  
  14. // Instances are not equal because of different value of property
  15. var_dump($object1 == $object2); // Will return bool(false)

Ok, PHP stwierdził, że obiekty nie są sobie równe - zgadza się.
Więc teraz użyłem obiektów mojej klasy, przekazałem różne wartości parametrów do konstruktora
Wartości parametrów są umieszczane we właściwościach klasy.

  1. echo "Start";
  2.  
  3. // Creating an instance of class with some parameters
  4. // Each of parameter will be stored as class property
  5. $object1 = new ComparsionRule('ABadasdC', ComparsionRule::LESS_THAN_OR_EQUAL);
  6.  
  7. // Creating an instance of class with some different parameters
  8. // Each of parameter will be stored as class property
  9. $object2 = new ComparsionRule('XYZ', ComparsionRule::NOT_EQUAL_TO);
  10.  
  11. // Two instances should not be equal (false expected)
  12. var_dump($object1 == $object2); // Will return bool(true)
  13.  
  14. // Printing content of first object
  15. var_dump($object1);
  16.  
  17. // Printing content of second object
  18. var_dump($object2);
  19.  
  20. // Checking the expression again
  21. // Two instances should not be equal (false expected)
  22. var_dump($object1 == $object2); // Will return bool(false)
  23.  
  24. echo "End";

Wynik jest zaskakujący, najpierw PHP stwierdza, że obiekty są sobie równe
Następnie wyświetla te obiekty i ponownie sprawdza czy są sobie równe, ale tym razem stwierdza, że jednak nie są równe
Załączam screenshot, na którym widać zawartość obu obiektów oraz te dziwne chwiejne wyniki porównania

(IMG:http://i43.tinypic.com/o7iuz5.png)

Go to the top of the page
+Quote Post
SmokAnalog
post
Post #2





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

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


Czy gdzieś po drodze do akcji nie wkraczają metody magiczne? Trudno tak zgadywać bez kodu klasy.
Go to the top of the page
+Quote Post
mstraczkowski
post
Post #3





Grupa: Zarejestrowani
Postów: 273
Pomógł: 52
Dołączył: 3.02.2013
Skąd: Przemyśl

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


Nie, nie używam zbyt często metod magicznych ze względu na wsparcie dla IDE i dla jasności kodu.
Jedyne metody magiczne, które są zaimplementowane i dotyczą także tej klasy to __construct() i __invoke()

Dla testu usunąłem metode __invoke(), jednak problem występuje nadal.
Kodu klasy niestety nie mogę udostępnić publicznie.

Kolejna ciekawostka:
Jeżeli usunę właściwość $_errorDefinitions to wtedy zachowanie wraca do normy.
Wygląda to tak jakby PHP analizował tylko pierwszą napotkaną właściwośc i tylko ją porównywał.

Podobnie jeżeli zamienie kolejność tj. type i compareValue zdefiniuje wcześniej niż errorDefinitions

Ten post edytował mstraczkowski 26.10.2013, 10:55:05
Go to the top of the page
+Quote Post
em1X
post
Post #4





Grupa: Zarejestrowani
Postów: 984
Pomógł: 41
Dołączył: 16.03.2002
Skąd: Płock

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


Po co porównywać dwa obiekty? Zobacz jak robi to Java. Utwórz sobie interfejs, np.
  1. interface Comparable
  2. {
  3. /**
  4.   * @param object $object Obiekt do porównania
  5.   * @returns bool Czy obiekty są identyczne
  6.   */
  7. public function equals($object);
  8. }


i sam definiuj kiedy obiekty rzeczywiście są podobne:
  1. class Person implements Comparable
  2. {
  3. protected $name;
  4.  
  5. public function __construct($name)
  6. {
  7. $this->name=$name;
  8. }
  9.  
  10. public function getName()
  11. {
  12. return $this->name;
  13. }
  14.  
  15. public function equals($object)
  16. {
  17. return $this->getName() === $object->getName();
  18. }
  19. }
  20.  
  21. $andrzej=new Person('Andrzej');
  22. $monika=new Person('Monika');
  23.  
  24. var_dump($andrzej->equals($monika));


Ten post edytował em1X 20.11.2013, 22:47:04
Go to the top of the page
+Quote Post
mstraczkowski
post
Post #5





Grupa: Zarejestrowani
Postów: 273
Pomógł: 52
Dołączył: 3.02.2013
Skąd: Przemyśl

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


Po to, aby sprawdzić czy taka instancja z takimi samymi właściwościami istnieje już w danej puli obiektów.

Mówiąc bardziej po ludzku:
W tym konkretnym przypadku, aby sprawdzić czy została już zdefiniowana taka sama reguła walidacyjna (instancja tej samej klasy z takimi samymi właściwościami)

Celem mojego tematu nie było otrzymanie alternatywnych rozwiązań, bo z tym nie mam problemu (rozwiązań jest sporo)
Chciałem tylko poznać odpowiedź na pytanie: "Dlaczego PHP w tej sytuacji tak się zachowuje"

Twój kod fajnie wygląda na banalnych przykładach, jednak w przypadku bardziej abstrakcyjnych rozwiązań
I dosyć sporej ilości klas nie za bardzo mam ochotę dokładać kolejny interfejs i implementować samodzielnie podobieństwa między obiektami
Tym bardziej, że PHP i jego dokumentacja deklaruje się, że operator porównania może to zrobić za mnie.

Doraźnie zastosowałem serializację obiektów i wyliczenie na jej podstawie sumy kontrolnej md5 w celu porównywania instancji
Zdaję sobie sprawę z tego, że nie jest to najlepsze rozwiązanie, ale tak jak mówię jest to rozwiązanie doraźne.

@edit 04.01.2014

Tak jak słusznie podejrzewałem, jest to bug w PHP
Zostawiam więc post dla potomnych (IMG:style_emoticons/default/smile.gif)

https://bugs.php.net/bug.php?id=66286

Ten post edytował mstraczkowski 4.01.2014, 02:15:23
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 22.08.2025 - 23:46