Article View: pl.comp.objects
Article #15717Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
From: Sektor van Skijlen
Date: Sun, 04 Mar 2007 22:09
Date: Sun, 04 Mar 2007 22:09
205 lines
10538 bytes
10538 bytes
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".
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ŚĆ).
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.
> Nie widzę szczególnego powodu, żeby wskaźniki nazywać "obiektami
> niewartościowymi", skoro pełnią one funkcję referencji, czy jak
> kto woli, identyfikatora obiektu.
Ależ wskaźniki są jak najbardziej typami wartościowymi, tylko i wyłącznie!
Tylko obiekty, które są przez te wskaźniki wskazywane, już niekoniecznie. W
szczególności, w idealnym projekcie powinno być tak, żeby wskaźnik nie był
potrzebny do czegokolwiek poza przyczynami czysto językowymi (czyli, inaczej,
żeby wartość tego wskaźnika w ogóle nikogo nie musiała interesować).
> 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.
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 Javie zresztą jest to urządzone niemal idealnie pod tym względem, tylko z
drobnymi zastrzeżeniami:
- Java nie pozwala na definiowanie własnych typów wartościowych
- Nie wprowadzono mechanizmu tupli, które mogłyby zastąpić niemożliwość
przekazania do metody zmiennej przez referencję
> > Jesli do porownania wartosci jak i tozsamosci istnieje
> > w danym jezyku ten sam operator to taki jezyk mozna sobie
> > usnac za syf, a nie jezyk
> Operator ten sam, pytanie na czym go użyjesz (na obiektach, czy na
> identyfikatorach obiektów, za które w C++ można uznać wskaźniki).
Problem w tym, że rozróżnienie typów jest wystarczające jeśli używamy osobnej
składni do określenia wartości i osobnej składni do okerślenia referencji.
Tak ma C++, pomijając przypadek, gdy jawnie używamy referencji.
Tak ma też Tcl - sama nazwa jest zawsze wyłącznie referencją, dopiero
poprzedzenie jej '$' oznacza wartość. W efekcie np. jak zrobisz:
proc compare {a b} { return $a == $b }
to potem wszystko zależy od tego, czy napiszesz
[compare x y]
czy
[compare $x $y]
> > Wiec jest doklandie odwrotnie niz piszesz:
> >
> > Chodzi o to, że maja być dostępny inny oparator do porownania
> > wartosci a inny do porownania tozsamosci obiektow
> Tak by było rzeczywiście najlepiej. Ale uważam, że operator == jest
> i tak lepszy w C++ niż w Javie. Bo niby dlaczego logiczna równość
> miałaby dotyczyć wyłącznie relacji bycia tym samym obiektem?
> Idealnie jest to w Pythonie: operator == jak w C++ i operator "is"
> jak w Javie.
Tak, tylko że jeśli "wierzymy w podział na obiekty wartościowe i
niewartościowe" (czytaj: mamy oczy tam gdzie trzeba), to relacja 'is' w
obiektach wartościowych jest nam zbędna, a '==' w obiektach niewartościowych
również nie ma sensu.
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.
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.
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).
A to się bierze stąd, że tożsamość obiektu decyduje nam o widoczności zmian.
Jeśli bowiem mamy dwa wskaźniki (a i b) wskazujące na jeden obiekt, to wtedy
po a->x = 10 możemy być pewni, że b->x == 10.
Dlatego też porównania wartości określonych stanów cząstkowych obiektów (nawet
jeśli obiekt ma tylko jeden taki stan) odbywają się tylko w ten sposób:
1. Porównanie wartości stanu z jakąś predefiniowaną stałą
2. Sprawdzenie, czy wartości stanu z dwóch różnych obiektów mają taką samą
wartość - ale również równą także jakiejś predefiniowanej stałęj
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?
> > 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.
BTW. akurat się zastanawiam nad tym, czy w Ginle dopuścić taką możliwość.
Oczywiście tworzenie na stosie nie wchodzi w rachubę tak czy siak, ale
chciałbym nie zabraniać możliwości tworzenia pod-obiektów jako pól. Czyli żeby
obiekty tych samych typów mogły być tworzone dynamicznie, a jednocześnie żeby
też mogły być polami.
--
// _ ___ 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:
<esfg25$b2m$1@kujawiak.man.lodz.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mailReferences:
<pl-comp-objects-faq-1-1166202604@ict.pwr.wroc.pl> <eru75v$dmm$1@bandai.magma-net.pl> <ervbaa$am4$1@inews.gazeta.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>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.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: Sun, 4 Mar 2007 22:09:09 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 205
Sender: Michal Malecki <sektor@zly.kis.p.lodz.pl>
Message-ID: <esfg25$b2m$1@kujawiak.man.lodz.pl>
References: <pl-comp-objects-faq-1-1166202604@ict.pwr.wroc.pl> <eru75v$dmm$1@bandai.magma-net.pl> <ervbaa$am4$1@inews.gazeta.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>
NNTP-Posting-Host: zly.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1173046149 11350 212.191.89.2 (4 Mar 2007 22:09:09 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Sun, 4 Mar 2007 22:09:09 +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