Article View: pl.comp.objects
Article #15719Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
From: Sektor van Skijlen
Date: Mon, 05 Mar 2007 21:28
Date: Mon, 05 Mar 2007 21:28
229 lines
11158 bytes
11158 bytes
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.
> > 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;
};
> > Po drugie, nie ma akurat kombinowania z tożsamością - jeśli mamy np. (no,
> > weźmy teraz Javę dla odmiany) dwie zmienne referencyjne, to ich porównanie
> > nie porównuje tych zmiennych referencyjnych, tylko ich wartości, a w
> > efekcie porównuje się tożsamości obiektów.
> Zgoda, z tym, że ja pisałem o C++.
Ależ w C++ masz to samo, tylko na wskaźnikach.
> >> 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?
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ć.
W C++ string jest typem wartościowym i spełnia wszystkie warunki dotyczące
typu wartościowego.
> > 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.
> > Drugie z kolei nie ma sensu dlatego, że porównania obiektów, jeśli już
> > istnieją, to zazwyczaj mają zupełnie inny wymiar. Jeśli już coś
> > porównujemy, to porównujemy stany, najczęściej określone stany cząstkowe.
> > Np. możemy porównywać samochody pod względem tego, czy są tego samego
> > koloru, albo tej samej marki, a także, czy jeden ma lepszego kopa od
> > drugiego. Ale nie bardzo możemy "porównać dwa samochody", no bo jak?
> >
> > Nawet w przypadku porządkowania obiektów, mamy do czynienia z określaniem
> > odpowiedniego kryterium porządkowania. Kryterium może być określone nawet
> > wielopoziomowo (np. uszeregować samochody wg marki, a jak są tej samej
> > marki to wg mocy silnika, a jak są nadal te same, to wg koloru itd.).
> >
> > 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?
> > 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.
> > 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ę :)
> 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.
> >> > 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 ;)
--
// _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `| /^\ ,() <ethouris(O)gmail.com>
// \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"Java is answer for a question that has never been stated"
Technical Details
Message-ID:
<esi21l$skh$1@kujawiak.man.lodz.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!newsfeed.pionier.net.pl!news.man.lodz.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>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!newsfeed.pionier.net.pl!news.man.lodz.pl!not-for-mail
From: Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid>
Newsgroups: pl.comp.objects
Subject: Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Date: Mon, 5 Mar 2007 21:28:21 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 229
Sender: Michal Malecki <sektor@zly.kis.p.lodz.pl>
Message-ID: <esi21l$skh$1@kujawiak.man.lodz.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>
NNTP-Posting-Host: zly.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1173130101 29329 212.191.89.2 (5 Mar 2007 21:28:21 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Mon, 5 Mar 2007 21:28:21 +0000 (UTC)
User-Agent: tin/1.6.2-20030910 ("Pabbay") (UNIX) (SunOS/5.9 (sun4u))
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit