Article View: pl.comp.objects
Article #15720Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
From: Mariusz Lotko
Date: Mon, 05 Mar 2007 23:15
Date: Mon, 05 Mar 2007 23:15
247 lines
11400 bytes
11400 bytes
Sektor van Skijlen wrote:
> Dnia Mon, 05 Mar 2007 07:07:47 +0100, Mariusz Lotko skrobie:
>> Sektor van Skijlen wrote:
>
>> > Dnia Sun, 04 Mar 2007 19:37:50 +0100, Mariusz Lotko skrobie:
>> >> Adam Karpierz wrote:
>> >
>> >> > "Sektor van Skijlen"
>> >> > <ethouris@guess.if.gmail.com.is.valid.or.invalid> wrote:
>> >> >>> if obj is anotherObj : # sprawdza czy to te same obiekty
>> >> >>> if obj == anotherObj : # sprawdza czy zawartość obiektów jest
>> >> >>> równa.
>> >> >>
>> >> >>> Czy o to Ci chodzi?
>> >> >>
>> >> >> Właśnie NIE o to mi chodzi.
>> >> >> Chodzi o to, że ma być dostępny TYLKO operator ==,
>> >> >> natomiast od definicji typu zależy czy porównuje on tożsamość,
>> >> >> czy wartość.
>> >
>> >> Tu się nie zgodzę. W przypadku C++ porównuje się zawsze wartość
>> >> obiektu. W przypadku wskaźnika wartością jest adres obiektu na
>> >> jaki wskaźnik wskazuje.
>> >
>> > No tak, ale jeśli porównujesz wartości wskaźnikowe, to de facto
>> > porównujesz tożsamości dwóch obiektów.
>> >
>> > Np. porównując "a == b" nie porównujesz "a" z "b", tylko porównujesz
>> > "tożsamość obiektu widocznego pod a" i "tożsamość obiektu widocznego
>> > pod b".
>
>> A jeśli obiektami są smart pointery, to co porównuję?
>
> To samo. Przecież ich wartości również są wskaźnikami.
Ale napisałeś (parę linijek wyżej), że porównywanie wskaźników, to
porównywanie tożsamości. Czy tożsamość przeradza się w wartość jeśli
obiekt jest inteligentny (smart)? ;-)
>
>> > Zresztą to się odnosi, jak słusznie zauważyłeś, ogólnie do wartości.
>> > Jeśli porównujesz dowolne dwa a i b tego samego typu, to porównanie
>> > określa ci, czy pod tymi dwiema zmiennymi siedzą te same wartości. W
>> > przypadku wskaźników będzie to oznaczało tylko to, czy te dwie zmienne
>> > wskaźnikowe wskazują na ten sam obiekt (czy na dwa różne). Jest to więc
>> > w efekcie porównanie tożsamości.
>> >
>> >> Operator == dla dwóch obiektów powinien _zawsze_ porównywać równość
>> >> semantyczną ich _zawartości_, a nie kombinować z ich tożsamością.
>> >
>> > Moment.
>> >
>> > Po pierwsze, równość dwóch obiektów powinna wynikać z równości ich
>> > wartości. Jeśli obiekt nie ma wartości, to nie powinien mieć określonej
>> > porównywalności, bo po prostu nie ma czego porównać. Porównujemy więc
>> > WARTOŚĆ (a nie za-WARTOŚĆ).
>
>> OK, w takim razie jakiś przykład obiektu bez wartości?
>
> struct X
> {
> int a;
> int* b;
> };
Czyli tak: jak mam wskaźnik osobno, to mogę go porównać, jak mam int osobno
to również mogę porównać, a jak je wezmę razem do kupy to już nie?
>> >> Każdą dowolną parę obiektów można w prosty sposób zweryfikować
>> >> pod kątem "czy to te same obiekty" mając do nich referencję, np.
>> >
>> >> bool teSame(const Klasa& a, const Klasa& b)
>> >> {
>> >> return &a == &b;
>> >> }
>> >
>> >> lub czy to równe obiekty
>> >> a == b
>> >
>> >> Co odpowiada konstrukcjom z Pythona jakie podalem w poprzednim poście.
>> >
>> > Można - tyle że tej pierwszej konstrukcji nikt nie stosuje.
>
>> Że jak? Piersza linijka większości porządnych operatorów == ! Po co
>> porównywać zawartość tego samego obiektu?
>
> A niby po co chcesz to sprawdzać? Jesteś pewny, że w każdym przypadku
> będzie to tańsze?
Mogę domniemywać, szczególnie jeśli obiekt składa się nie tylko z typów
prostych, a więc "rekursywnie" będą wywołane inne operatory porównania jeśli
tego nie zrobię.
>
> Jeśli w danym obiekcie w operatorze == nastąpi porównanie tylko jednej
> wartości, to oszczędzasz tylko w przypadku, gdy masz ten sam obiekt. Jeśli
> nie, to masz dodatkowe, niepotrzebne porównanie. Czyli koszt jest mniejszy
> w przypadku równości, ale większy w przypadku nierówności.
>
>> > W Javie np. masz:
>> >
>> > Klasa a, b;
>> > int c, d;
>> >
>> > i masz
>> > a == b
>> > c == d
>> >
>> > i bez różnicy. Szkoda tylko, że dla "String t, s" jest to samo ;)
>> >
>> > Nie możesz jednak w żaden sposob (inny niż przez odpowiednie metody)
>> > porównać wartości a i b, ani porównać referencji c i d.
>
>> W C++ też musisz wiedzieć co porównujesz. Bo jeśli a i b są wskażnikami,
>> to masz analogiczny problem. Z tym, że zamiast equals() używasz * do
>> wyłuskania wartości.
>
> Nieprawda. Jeśli c i d są typami wartościowymi, to ich wskaźniki w ogóle
> nie powinny cię interesować.
Ale mogą i język C++ tego nie zabrania. Jaki więc sens ma Twoja teoria w
odniesieniu do tego języka?
>> > Pierwsze nie ma sensu dlatego, że jeśli w typach wartościowych liczy
>> > się dla nas wartość, to nie liczy się tożsamość. Porównując wartość do
>> > wspomnianego koloru, interesuje nas kolor, a nie np. czy kartki
>> > papieru, na których zapisano kod koloru, są te same, czy inne.
>
>> W szczególności może się zdarzyć, że będziemy chcieli porównać kolor tego
>> samego egzemplarza kartki. Wówczas porównanie będzie prostsze i wykonalne
>> nawet dla daltonisty. Stąd chyba nie warto od tożsamości się odcinać.
>
> Ale PO CO?
>
> Zwróć uwagę na to, co napisałem poniżej: nigdy nie porównuje się dwóch
> wartości stanów z dwóch różnych obiektów, jeśli nie mamy z innego źródła
> informacji o tym, jaka ta wartość jest.
Twoja teoria stoi na glinianych nóżkach. Wprawdzie nie mam pamięci
absolutnej, ale gdzieś mi kołacze po głowie, że kilka Twoich "nigdy"
już mi się w życiu zdarzyło. A że nie pamiętam, to chyba nie skończyło
się to żadną katastrofą programistyczną, którą trzebaby w pośpiechu
naprawiać.
>> > Dlatego właśnie obiekty nie mają zwykle takiej ogólnej "wartości", mają
>> > ich zwykle wiele i różne wartości mogą nas interesować przy
>> > porównaniach.
>
>> Piszesz trochę w kontekście bazodanowym, gdzie jest np. poszukiwanie
>> obiektów spełniających określone kryteria. Jest jednak cała gama klas,
>> dla których bez większych trudności można zdefiniować operatory
>> porównania.
>
> To są to wtedy typy wartościowe.
>
> Java próbuje symulować to poprzez wprowadzanie obiektów niezmienialnych,
> jak właśnie String (w C# wyszło to o tyle lepiej, że tam jest dla tego
> typu poprawnie zdefiniowany operator porównania). Niestety z przyczyn
> wydajnościowych wymaga to dodatkowych wygibasów jak StringBuilder.
>
>> Mimo to nie odważyłbym się na takie wyraźne i jednoznaczne nazwanie
>> pierwszych obiektów wartościowymi a drugich niewartościowymi.
>
> Dlaczego?
Bo świat to nie tylko bazy danych.
>
>> > Ja wiem, że zaraz ktoś rzuci szczególnym przypadkiem, że co z
>> > obiektami, które mają jedno pole, a zatem tylko jeden stan cząstkowy?
>> >
>> > Otóż tutaj właśnie odgrywa rolę kwestia tożsamości obiektów. Jeśli
>> > bowiem interesuje nas tożsamość obiektu, to nie interesuje nas jego
>> > wartość (jeśli nie podlega ona bieżącemu przetwarzaniu, tzn. np.
>> > właśnie chcielibyśmy tą wartość porównać z odpowiadającym temu czemuś
>> > stanem w innym obiekcie).
>
>> Weźmy obiekty w rodzaju mutable string. Da się jednoznacznie zdefiniować
>> operator porównania, w pewnej chwili dwa obiekty będą równe, a za chwilę
>> nie, więc trudno tu mówić o tożsamości.
>
> Tak, ale mutable string - jeśli mówimy o czymś takim, jak StringBuilder -
> nie jest już typem wartościowym, gdyż zmienność obiektu wchodzi w
> interakcję z jego tożsamością.
>
> Porównanie tego typu z innym mogłoby się odbywać tylko poprzez -
> najczęściej niejawne - pozyskanie String'a - czyli typu już wartościowego
> - i porównanie go z innym stringiem.
Rozumiem, że String jest niezmienialny a SB zmienialny, ale dlaczego jeden
jest wartościowy, a drugi już nie - wstyd się przyznać, ale nie mogę.
>> > Natomiast porównanie stanów dwóch obiektów nie ma po prostu sensu. Co
>> > na przykład da ci informacja, że pewne dwa samochody są "tego samego
>> > koloru", dopóki nie wiesz, jaki to kolor?
>
>> Uwierz mi, w wielu sytuacjach ma to sens.
>
> Nie wierzę :)
Znowu zrobię niecodzienną w świecie informatyki wycieczkę: załóżmy jesteś na
dyskotece i jesteś stanu wolnego. Jeśli nie zainteresujesz się stanem
obiektu "kobieta" (czy też jest "wolny") przed zagajeniem, to ryzykujesz
stratę zębów od jej chłopaka-dresiarza.
>
>> Dziwię się Twoją opinią, bo sprawiasz wrażenie człowieka, który ma
>> doświadczenie zawodowe i trochę linii kodu wyprodukował.
>
> I mówię to właśnie na podstawie tego :)
>
> Jeśli chcemy stwierdzić, czy dwa obiekty są w "tym samym stanie", to
> musimy mieć chociaż przybliżone pojęcie o tym, jaki ten stan jest.
A jeśli chcemy je tylko pogrupować według stanu?
>
>> >> > Podobnie chodzi o to aby byl dostepny inny operator do
>> >> > 'clone' obiektu a inny do zmiany referencji
>> >
>> >> To też jest w C++ rozgraniczone:
>> >> C o1 = inny; // kopiowanie obiektu
>> >> C* o2 = &inny; // przypisywanie "referencji".
>> >> C& o3 = inny; // przypisywanie referencji.
>> >
>> >> Schody zaczynają się, gdybyśmy napisali
>> >> o3 = jeszcze_inny; // ... bo to już znowu jest kopiowanie, a nie
>> >> zmiana
>> >> // referencji
>> >
>> >> No ale taki już jest ten C++...
>> >
>> > Ale w C++ zwykle - poza szczególnymi przypadkami - nie stosuje się dla
>> > tego samego typu operowania statycznego i dynamicznego. Czyli, jeśli
>> > używamy wskaźników i new, to obiektów tego samego typu już nie tworzymy
>> > na stosie.
>
>> A "my" stosujemy, jeśli jest taka potrzeba... :-)
>
> I to prowadzi potem do ciekawych kwiatków ;)
Jeden z moich kolegów komentując efekt nieprzemyślanego wymagania
powiedział: "trzeba wiedzieć o co się prosi...".
--
Mariusz Lotko
Technical Details
Message-ID:
<esi7ve$5ia$1@bandai.magma-net.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.magma-net.pl!not-for-mailReferences:
<pl-comp-objects-faq-1-1166202604@ict.pwr.wroc.pl> <pan.2007.02.26.21.12.45.8078@go2.pl> <es6b6u$2ls$1@kujawiak.man.lodz.pl> <esbllu$51n$1@bandai.magma-net.pl> <esbv7t$7o$1@kujawiak.man.lodz.pl> <1172940339.25227.28.camel@qrnik> <escc9e$2h2$1@kujawiak.man.lodz.pl> <esd1k1$9bp$1@bandai.magma-net.pl> <esemb6$2r3$1@kujawiak.man.lodz.pl> <eses6u$8fm$1@inews.gazeta.pl> <esf3am$r52$1@bandai.magma-net.pl> <esfg25$b2m$1@kujawiak.man.lodz.pl> <esgboa$8i2$1@bandai.magma-net.pl> <esi21l$skh$1@kujawiak.man.lodz.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.magma-net.pl!not-for-mail From: Mariusz Lotko <imie.nazwisko@wp.pl> Newsgroups: pl.comp.objects Subject: Re: pl.comp.objects FAQ (Frequently Asked Questions and more) Date: Tue, 06 Mar 2007 00:15:37 +0100 Organization: Magma Systemy Komputerowe Lines: 248 Message-ID: <esi7ve$5ia$1@bandai.magma-net.pl> References: <pl-comp-objects-faq-1-1166202604@ict.pwr.wroc.pl> <pan.2007.02.26.21.12.45.8078@go2.pl> <es6b6u$2ls$1@kujawiak.man.lodz.pl> <esbllu$51n$1@bandai.magma-net.pl> <esbv7t$7o$1@kujawiak.man.lodz.pl> <1172940339.25227.28.camel@qrnik> <escc9e$2h2$1@kujawiak.man.lodz.pl> <esd1k1$9bp$1@bandai.magma-net.pl> <esemb6$2r3$1@kujawiak.man.lodz.pl> <eses6u$8fm$1@inews.gazeta.pl> <esf3am$r52$1@bandai.magma-net.pl> <esfg25$b2m$1@kujawiak.man.lodz.pl> <esgboa$8i2$1@bandai.magma-net.pl> <esi21l$skh$1@kujawiak.man.lodz.pl> NNTP-Posting-Host: 192.168.21.22 Mime-Version: 1.0 X-Trace: bandai.magma-net.pl 1173136174 5706 192.168.21.22 (5 Mar 2007 23:09:34 GMT) X-Complaints-To: usenet@news.magma-net.pl NNTP-Posting-Date: Mon, 5 Mar 2007 23:09:34 +0000 (UTC) User-Agent: KNode/0.10.4 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit