Thread View: pl.comp.objects
79 messages
79 total messages
Page 1 of 2
Started by Kamil Konieczny
Fri, 15 Dec 2006 17:10
Page 1 of 2 • 79 total messages
pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Kamil Konieczny
Date: Fri, 15 Dec 2006 17:10
Date: Fri, 15 Dec 2006 17:10
692 lines
27580 bytes
27580 bytes
Posted-By: auto-faq 3.1.1.2
Archive-name: pl-comp-objects-faq
---------------------------------------------------------------------------
Zawartosc: pl.comp.objects FAQ (Frequently Asked Questions and Summary)
Data: 1998.08.18
Wersja: 3.2
Autorzy: Kuba Chabik
Kamil Konieczny kkoniec@mks.com.pl
---------------------------------------------------------------------------
Wykorzystane materialy: poprzednia (druga) edycja FAQ, opracowana przez
Maciej "MACiAS" Pilichowski, macias@vm.cc.uni.torun.pl
Data opracowania: 2.05.95 - 16.05.95
Zasoby: 6.12.94 - 12.04.95
-------
Uwagi:
[ts 2005.12.27]
To FAQ jest juz tak stare, ze chyba az przestarzale. Ale dopoki ktos
nie wymysli nowego, to z braku innego bedzie wysylane nadal. Moze ktos
sie zlituje i napisze/poprawi?
[Kamil 1998.06.24]:
Ze wzgledu na brak czasu edycja trzecia to glownie reorganizacja
i poprawienie poprzedniej edycji, autorstwa [MACiAS].
W miare wolnego czasu bede dodawal nowe tematy, zaczynajac od biezacych
listow az do zamierzchlej przeszlosci, czyli od roku 1998 do 1995.
Nie beda dodawane tematy, nie majace nic (albo niewiele) wspolnego
z tematyka grupy.
Postaram sie rowniez o usuwanie z archiwow listy spamow,
jak rowniez nieaktualnych ogloszen zwiazanych z obiektami.
[MACiAS 1995.05.16]:
W znakomitej wiekszosci wszystkie informacje zostaly wziete z listow
uczestnikow grupy. Jesli zauwazycie ponizej bledy, niescislosci, luki,
etc. to bardzo prosze o listy (jesli sprawa nie jest oczywista, to
najlepiej na adres grupy).
-------
Krotki spis tematow:
T.1 Informacje ogolne (literatura, slowniczek, pojecia).
T.2 Jezyk C++.
T.3 Jezyk Smaltalk.
T.4 Inne
-------
Spis tematow:
T.1.1 Literatura.
T.1.1.1 Literatura w jezyku angielskim.
T.1.1.2 Literatura w jezyku polskim.
T.1.2 Proponowany maly slownik terminow.
T.1.3 Co to jest klasa?
T.1.4 Co to jest metoda?
T.1.5 Co to jest atrybut?
T.1.6 Co reprezentuje dziedziczenie?
T.1.7 Co to jest polimorfizm?
T.1.8 Co zyskujemy przez polimorfizm?
T.1.9 Do czego potrzebna jest hermetyzacja?
T.1.10 Co to jest klasa abstrakcyjna?
T.1.11 Co to jest metaklasa?
T.1.12 Co to jest komponent?
T.1.13 Co to sa obiektowe bazy danych?
T.1.14 Czy obiektowe bazy danych sa gorsze od relacyjnych?
T.1.15 Co to jest CORBA?
T.1.16 Czy programy obiektowe sa wolniejsze od proceduralnych?
T.2.1 Jak w prosty sposob zrozumiec opis bledu w BC++?
T.2.2 Co zrobic jesli klasa deklarowana w pliku naglowkowym uzywa typow
T.2.3 Co to sa dziwne pliki w katalogu "/usr/g++-include/gen" z
T.2.4 Jak w C++ obsluguje sie funkcje ze zmienna liczba parametrow?
T.2.5 Czy mozna zaimplementowac funkcje wirtualne w C?
T.2.6 Czy stosowanie zaprzyjazniania klas nalezy do dobrej praktyki
T.2.7 Gdzie mozna dostac gramatyke C++ (obojetnie dla jakiego narzedzia,
T.2.8 Czy przejscie do OOP wymaga odrzucenia "balastu proceduralnego"?
T.2.9 Co to jest konstruktor kopiujacy?
T.2.10 Czy istnieje domyslny konstruktor kopiujacy?
T.2.11 Jak uniknac dolaczania metod wirtualnych, z ktorych nie korzystam, a
T.2.12 Ciekawostki z historii C++.
T.2.13 Stosowac wskaznik czy referencje?
T.2.14 Co to sa sprytne wskazniki (smart pointers)?
T.2.15 Czy wszystkie metody w mojej klasie powinny byc wirtualne?
T.2.16 Czy konstruktory moga byc wirtualne?
T.2.17 Jak tworzyc klasy abstrakcyjne?
T.3.1 Czy jest dostepna darmowa implementacja Smalltalka?
T.3.2 Czy SmallTalk jest dobry w praktyce, czy tylko w teorii?
T.3.3 Gdzie mozna dowiedziec sie o jezyku Smalltalk i jego zastosowaniach?
T.4.1 Jak powinienem zabrac sie za programowanie obiektowe?
T.4.2 Czy OOP oznacza brak optymalizacji?
T.4.3 Jak rozpoznawac, czy dany program lub projekt jest dobry ?
T.4.4 Poszukuje informacji na temat rozszerzen do jezykow obiektowych
---------------------------------------------------------------------------
-------
T.1.1 Literatura.
T.1.1.1 Literatura w jezyku angielskim.
Badouin-Lafon M., "Object-Oriented Languages"
wyd ?, ISBN ?
Brown W.H., Malveau R.C., McCormick H.W. III, Mowbray T.J.,
"AntiPatterns: Refactoring Software, Architectures,
and Projects in Crisis."
John Wiley & Sons, ISBN 0-471-19713-0
Buchmann et al., "A System of Patterns"
John Wiley & Sons, ISBN 0-471-95869-7
Budd, T., "An Introduction to Object Oriented Programming",
Addison Wesley Publishing, ISBN 0-201-54709-0
Coleman D., et al, "The Fusion Method"
wyd ?, ISBN ?
Fowler M., Scott K., "UML Distilled"
Addison-Wesley, ISBN 0-201-32563-2
Gamma E., Helm R., Johnson R., Vlissides J. "Design Patterns"
Addison-Wesley, ISBN 0-201-63361-2
Graham I., "Object-Oriented Methods" 2nd ed.
Addison-Wesley, ISBN 0-201-59371-8
http://www2.awl.com/cseng/
Jacobson I., Christerson M., Johnsson P., Overgaard G.,
"Object-Oriented Software Engineering"
Addison-Wesley, ISBN 0-201-54435-0
Lakos J., "Large-Scale C++ Software Design"
Addison-Wesley, ISBN 0-201-63362-0
Lalonde W.R., Pugh J.R., "Inside Smalltalk", Volume 1 and 2,
Prentice Hall, ISBN ?
Rumbaugh J., Blaha M., Premerlani W.,Eddy F.,Lorensen W.,
"Object-Oriented Modelling and Design"
Prentince Hall, ISBN ?
Stroustrup B., "The C++ Programming Language" 3rd. ed., 6th printing
Addison-Wesley, ISBN 0-201-88954-4
http://www.research.att.com/~bs/homepage.html
T.1.1.2 Literatura w jezyku polskim.
Barteczko K., "Praktyczne wprowadzenie do programowania w jezyku C++",
LUPUS, ISBN ISBN 83-85545-13-1
Coad P., Yourdon E., "Analiza obiektowa" (OOA),
README, ISBN 83-85769-17-X
Coad P., Yourdon E., "Projektowanie obiektowe" (OOD),
README, ISBN 83-85769-18-8
Coad P., Nicola J., "Programowanie obiektowe" (OOP),
README, ISBN 83-85769-16-1
Grebosz J., grebosz@bron.ifj.edu.pl, "Symfonia C++"
Oficyna Kallimach, ISBN 83-901689-0-1 wydanie 3,
Oficyna Kallimach, ISBN 83-901689-1-X
Grebosz J., "Pasja C++"
Oficyna Kallimach, ISBN 83-901689-2-8
Hansen T., "Zadania z jezyka C++",
WNT, ISBN 83-204-1759-7
Kliszewski M., "Inzynieria oprogramowania obiektowego - analiza obiektowa",
RESPEKT, ISBN 83-901994-0-8
Kain E., "Od C do C++"
wyd ?, ISBN ?
Lippman S.B., "Podstawy jezyka C++", Tlumaczenie z wydania 2,
WNT, ISBN 83-204-1681-7
Martin J., Odell J.J., "Podstawy metod obiektowych"
WNT, ISBN 83-204-2116-0
Stroustrup B., "Jezyk C++", Tlumaczenie wydania 2,
WNT, ISBN 83-204-1697-3
Stroustrup B., "Projektowanie i rozwoj jezyka C++",
WNT, ISBN 83-204-2042-3
-------
T.1.2 Proponowany maly slownik terminow.
garbage collector - odsmiecacz
operator overloading - przeciazanie operatora
object persistency - trwanie obiektu
persistent pointer - trwaly wskaznik
container - pojemnik
template - szablon
reference - odnosnik
dereferencing - wyluskiwanie
-----
T.1.3 Co to jest klasa?
Klasa jest abstrakcja obiektow z modelowanej dziedziny. Stanowi
wzorzec, opis, z ktorego te obiekty beda tworzone. Klasa nic nie
"robi", klasa czyms "jest". Klasy odwzorowuja przedmioty, osoby, a
takze organizacje i procesy zachodzace w swiecie rzeczywistym.
Klasa posiada jakas odpowiedzialnosc. Cos, dla czego nie potrafisz
wskazac odpowiedzialnosci, klasa nie jest (najprawdodobniej jest
jedyniem atrybutem innej klasy).
-----
T.1.4 Co to jest metoda?
Metoda, zwana takze operacja, reprezentuje czynnosc, jaka moze byc
wykonana przez dany obiekt w swiecie rzeczywistym. Metody moga
uzywane do uzyskania informacji lub do zmiany stanu danego obiektu.
-----
T.1.5 Co to jest atrybut?
Atrybut to cecha obiektu, na przyklad kolor pojazdu, dlugosc tekstu,
wzrost osoby. Atrybuty sa innymi obiektami zagniezdzonymi w danym
obiekcie.
-----
T.1.6 Co reprezentuje dziedziczenie?
Dziedziczenie reprezentuje specjalizacje. Mowimy, ze klasa
dziedziczaca (subclass) "jest rodzaju" klasy bazowej (superclass).
Innymi slowy, klasa bazowa reprezentuje pojecie bardziej ogolne, niz
klasa dziedziczaca.
-----
T.1.7 Co to jest polimorfizm?
Metody polimorficzne to takie, ktore moga zachowywac sie roznie, w
zaleznosci od tego, na rzecz jakiego konkretnego obiektu zostaly
wywolane. Metode polimorficzna mozemy przedefiniowac w klasie
implementujacej interfejs (czyli, najczesciej, dziedziczacej). Jezeli
teraz inne obiekty beda wywolywac te metode dla obiektow nowej klasy,
to bedzie wykonywala sie nowo, a nie stara metoda, choc same obiekty
wolajace nie zauwaza zmiany.
-----
T.1.8 Co zyskujemy przez polimorfizm?
Dzieki polimorfizmowi uzyskujemy elastycznosc systemow, bowiem mozemy
modyfikowac jedynie to, co rzeczywiscie nalezy zmienic, nie zas cale
"otoczenie" konkretnej metody
-----
T.1.9 Do czego potrzebna jest hermetyzacja?
Hermetyzacja, czyli ukrywanie metod i atrybutow klas, daje nam
bezpieczenstwo i przejrzystosc. Przypuscmy, ze mamy atrybut
"godzinaRozpoczecia" klasy "Wyklad". Gdyby wszyscy mieli dostep do
takiego atrybutu, mogloby sie zdarzyc, ze ktos ustawilby ja na liczbe
wieksza od 23, co oczywiscie nie ma sensu. Jednakze dzieki
hermetyzacji mozemy taka kontrole poprawnosci zawrzec w metodzie
"zmienGodzineRozpoczecia" i odmowic ustawienia nieprawidlowej
godziny.
-----
T.1.10 Co to jest klasa abstrakcyjna?
To taka klasa, ktora mozna tylko wykorzystywac przez dziedziczenie od
niej, a nie mozna tworzyc jej obiektow. Klasy abstrakcyjne
reprezentuja pojecia, ktore sa generalizacja innych pojec, ale same w
sobie nie reprezentuja zadnych obiektow w dziedzinie.
-----
T.1.11 Co to jest metaklasa?
Metaklasa to jakby klasa dla klasy, innymi slowy, egzemplarze
(instance) metaklas sa klasami. Metaklasy wystepuja nie we wszystkich
jezykach programowania, a nawet w tych, w ktorych wystepuja, trudno
wskazac ich konkretne, programistyczne zastosowanie. Jednakze czesto
stosuje sie jej nawet o tym nie wiedzac.
-----
T.1.12 Co to jest komponent?
Komponent to grupa klas, ktore sluza jednemu, konkretnemu celowi.
Klasy w komponencie charakteryzuja sie tym, ze maja silne powiazania
z innymi klasami wewnatrz tego samego komponentu i slabe poza nim.
Dzieki temu komponent moga byc rozwijane niezaleznie i podmieniane w
razie potrzeby, bez modyfikacji innych komponentow. Przykladem
komponentu moglaby byc grupa klas odpowiedzialna za obsluge wydruku.
-----
T.1.13 Co to sa obiektowe bazy danych?
Pojecie "bazy danych" nie jest szczegolnie szczesliwe. Lepiej mowic o
"obiektach trwalych". Systemy takie pozwalaja na przechowanie stanu
obiektu pomiedzy wywolaniami aplikacji, czyli tak, jak tradycyjna
baza danych przechowuje dane. Jednakze roznica miedzy nimi a takimi
bazami polega na fakcie, ze nie trzeba programowo odtwarzac stanu
aplikacji z bazy (np. zapytaniami SQL). Po prostu obiekty aplikacji i
obiekty bazy danych to to samo.
-----
T.1.14 Czy obiektowe bazy danych sa gorsze od relacyjnych?
To zalezy do czego. W przypadku odwzorowywania skomplikowanych
zaleznosci sa o niebo lepsze. W przypadku plaskich, kartotekowych
danych sa gorsze. Technologia ODBMS jest niewatpliwie mniej dojrzala
od RDBMS, jednakze swoj okres "dzieciecy" ma juz na pewno za soba.
-----
T.1.15 Co to jest CORBA?
CORBA to skrot od Common Object Request Broker Architecture. Jest to
architektura, ktore umozliwia komunikacje obiektom zlokalizowanym na
roznych maszynach, roznych systemach operacyjnych, roznych
architekturach sprzetowych komunikacje miedzy soba. W ramach
standardu CORBA istnieja takze uslugi (CORBA services), np. kolekcje,
zdarzenia (events), transakcje i inne. CORBA jest bardzo potezna
architektura, ale nie ma zbyt dobrych implementacji, szczegolnie
uslug. Ponadto organizacja OMG, ktora zdefiniowala CORBA'e, jest
cialem biurokratycznym i nieruchawym. Spowalnia to rozwoj tego
standardu.
-----
T.1.16 Czy programy obiektowe sa wolniejsze od proceduralnych?
Nie, to kompletna bzdura. Programowanie obiektowe pozwala na
zastosowanie takich technik, ktore czynia program bezpieczniejszym,
stabilniejszym, szybszym i bardziej elastycznym. Ponadto, technologia
obiektowa pozwala tworzyc system w sposob bardziej rygorystyczny, a
wiec pewniejszy i bardziej skoordynowany, niz technologia
proceduralna. Skutkiem jest generalnie wyzsza jakosc systemow,
szczegolnie tych powazniejszych, a wiec i wieksza szybkosc ich
dzialania.
Opinie taka programy obiektowe zawdzieczaja niedouczonym
programistom, ktorzy, liznawszy odrobiny C++, poczuli sie ekspertami
od obiektow i wyglaszali na prawo i lewo podobne bzdury.
---------------------------------------------------------------------------
-----
T.2.1 Jak w prosty sposob zrozumiec opis bledu w BC++?
Przeczytac opis bledu, zajrzec do "Programmer's Manual",
"Programmer's Reference", podrecznika C++.
Jesli nie pomoze, skontaktowac sie z innymi osobami piszacymi w C++.
-----
T.2.2 Co zrobic jesli klasa deklarowana w pliku naglowkowym uzywa typow
deklarowanych w innych plikach naglowkowych?
W _kazdym_ pliku naglowkowym nalezy wpisac:
#ifndef nazwapliku_h
#define nazwapliku_h
..
#endif
I mozesz bezkarnie wlaczac potrzebne ci headery.
-----
T.2.3 Co to sa dziwne pliki w katalogu "/usr/g++-include/gen" z
roszerzeniami ".ccP" oraz ".hP"?
Jest to po prostu biblioteka "libg++". Dowiedziec sie czegos wiecej mozesz
z dokumentacji. A pliki z rozszerzeniem ".ccP" i ".hP" sa wejsciowymy
plikami do programu "genclass". To sa pliki ze starej wersji kompilatora,
ktory nie mial wlaczonych templates, wiec uzywalo sie tego i "genclass"
specyfikujac jaki mial byc bazowy typ, "genclass" tworzyl z tego pliki
np. "<type>Vec.cc" i "<type>Vec.h" zastepujac <T> podanym typem.
-----
T.2.4 Jak w C++ obsluguje sie funkcje ze zmienna liczba parametrow?
W starym C stosowalo sie <varargs.h>, w nowym (ANSI C oraz C++)
stosuje sie <stdarg.h>.
Ponizej przyklad programu wykorzystujacy <stdarg.h>.
va_list - typ zmiennej pomocniczej
va_start - inicjalizacja listy
va_argptr - przesuniecie wskaznika listy na nastepny element
#include <stdio.h>
#include <stdarg.h>
void pisz(char *tekst,...)
{
va_list argptr;
va_start(argptr,tekst);
printf("\nTo sa dane : %s",tekst);
while(*(tekst=va_arg(argptr,char *))!=NULL)
printf(" %s",tekst);
va_end(argptr);
};
void main()
{
pisz("ala","ola","kot","domek na prerii","i nic",NULL);
};
Typowo to jest tak, ze pierwszy parametr zawiera informacje o liczbie
dalszych parametrow. Moze to byc liczba, ale moze byc tak jak w "printf":
printf("zmienna %s = %d",...)
Tu jest podane, ze tylko dwoch parametrow trzeba sie doszukac.
-----
T.2.5 Czy mozna zaimplementowac funkcje wirtualne w C?
Tak - mozna to zrobic poprzez umieszczenie wskaznikow do funkcji razem
z danymi, np:
struct ojciec {
int daneojca;
int *funkcjaWirtualna(char *arg);
};
struct syn {
struct ojciec o;
int danesyna;
int *mojaFunkcjaWirtualna();
};
struct syn *konstuktor_syna()
{
struct syn *s = malloc(...);
s->mojaFunkcjaWirtualna = syn_mojaFunkcja;
s->o.funkcjaWirtualna = s->mojaFunkcjaWirtualna; // podmiana wskaznika
// funkcji wirtualnej
}
czyli poprzez podmiane wskaznika do funkcji. Taka realizacja jednak
umozliwa jednak uzywanie tylko pseudo-wirtualnych funkcji. Jesli chcemy
uzywac naprawde takich funkcji uzyjmy jezyka obiektowego, gdyz w tych
jezykach funkcja/metoda wirtualna wyroznia sie tym, ze niezaleznie od
sposobu wywolania zawsze wykonana zostanie funkcja odpowiadajaca
rzeczywistemu typowi klasy. Tak jak w ponizszym przykladzie:
foobar( struct ojciec *o)
{
o->mojaFunkcjaWirtualna(); // jesli o jest wskaznikiem na syna
// to wywolane zostanie syn_mojaFunkcja
}
-----
T.2.6 Czy stosowanie zaprzyjazniania klas nalezy do dobrej praktyki
programisty?
Nie, gdyz dopuszcza do latwego dostepu do pol prywatnych i
chronionych. Narusza to zasade "jedyna aktywnosc systemu
obiektowego to przekazywanie wiadomosci (message passing)". Istnieje
roznica miedzy zapisaniem "kolo->radius=5;", a "kolo->setRadius(5);".
-----
T.2.7 Gdzie mozna dostac gramatyke C++ (obojetnie dla jakiego narzedzia,
preferowane yacc(bison), lex(flex) itp), ale koniecznie AT&T 2.0
(glownie chodzi o nested classes oraz templates)?
Powinna byc w zrodlach GNU cc.
Jest rowniez w B.Stroustrup "The C++ Programming Language", 3rd ed.,
Appendix A (niekompletna).
-----
T.2.8 Czy przejscie do OOP wymaga odrzucenia "balastu proceduralnego"?
Wczytujac sie w Stroustrupa "Jezyk C++" mozna zauwazyc jego
slowa: nowe techniki programowania nie neguja starych - uzupelniaja je.
To nie rewolucja. Tam gdzie wystarcza procedury lub moduly, nie szukamy
obiektow.
[czy ktos moze znalezc nr rozdzialu i paragrafu, lub nr strony ? Kamil]
-----
T.2.9 Co to jest konstruktor kopiujacy?
Konstruktor kopiujacy jest bardzo podobny do operatora przypisania,
tyle ze o ile operator przypisania uzywany jest dla obiektow juz
istniejacych, to konstruktor kopiujacy gdy tworzymy nowy obiekt i
jednoczesnie nadajemy mu jakas wartosc. Przyklad (bo bez przykladu
raczej malo kto zrozumie :-) ):
class A
{
private:
int data;
public:
A(int new_data=0) : data(new_data) {}; // To jest zwykly
// konstruktor
A( A& a ) : data(a.data) {}; // A to konstruktor kopiujacy
A& operator=(A &a) { data=a.data; return *this; } // a to
// operator przypisania
};
I teraz...
main()
{
A a(1); // Tu zostanie wywolany zwykly konstruktor, z argumentem 1
A b; // Podbnie, tyle ze argument zostanie domyslnie
// przyjety jako 0
A c=b; // Tutaj konstruktor kopiujacy z argumentem b
A d; // A tutaj operator przypisania z tym samym argumentem
d=b;
};
Najwazniejsze w tym wszystkim sa ostatnie trzy linijki, bo tutaj
wlasnie widac roznice, kiedy wywolywany jest operator przypisania, a
kiedy konstruktor kopiujacy. Konstruktor kopiujacy jest tylko i
wylacznie wtedy gdy przypisanie nastepuje rownoczesnie z utworzeniem.
Dlaczego to wyroznienie? Pozwala to zaoszczedzic operacji, bo
oczywiscie moglo by byc i tak ze kazda instrukcja typu "A b=c;"
bylaby rozbijana na dwie: "A b; b=c;". Ale wtedy niepotrzebnie obiekt
"b" bylby dwa razy inicjowany (w naszym przypadku najpierw "data=0",
a potem "data=c.data").
Taka instrukcja jak "A b=c;" jest rownowazna po prostu "A b(c);"
a nie (jak mogloby sie wydawac) parze instrukcji "A b; b=c;".
Ponizsze przyklady takze sa ciekawe:
class klasaA {
public:
klasaA metoda() { return (*this); };
...
};
Tutaj zostanie najpierw wykonana kopia obiektu (poprzez wywolanie
kostruktora kopiujacego) i kopia zostanie zwrocona jako wynik metody;
Trzeba bardzo uwazac na brak znaczku referencji "&"!!!
class klasaA {
public:
klasaA& metoda()
{
klasaA temp;
....
return temp;
};
....
};
Poniewaz "temp" jest obiektem o czasie zycia tylko wewnatrz metody, wiec by
moc zwrocic referencje do niego trzeba miec kopie o zasiegu wiekszym.
Kopilator wiec wola konstruktor kopiujacy z argumentem "temp" i tworzy jego
kopie na stercie i zwraca referencje do nowego obiektu.
-----
T.2.10 Czy istnieje domyslny konstruktor kopiujacy?
Tak - kopiuje poszczegolne pola. Z tego powodu nie nadaje sie
do klas zawierajacych wskazniki - w efekcie otrzymujemy dwa obiekty
wskazujace na ten sam (trzeci) obiekt. Jezeli teraz jeden z tych
obiektow zostanie usuniety, to najprawdopodobniej zostanie tez
zniszczony obiekt przez niego wskazywany, i drugi z obiektow bedzie
wskazywal cos blednego. Dlatego tez gdy uzywamy operacji przypisania,
a dana klasa zawiera wskazniki, to trzeba konstruktor kopiujacy
zdefiniowac samemu, umieszczajac w nim operacje potrzebne do
utworzenia kopii obiektu wskazywanego przez wskaznik.
-----
T.2.11 Jak uniknac dolaczania metod wirtualnych, z ktorych nie korzystam, a
sa zadeklaroawne w definicji objektu?
Pozne laczenie ("late binding"), ktore UMOZLIWIA tworzenie metod
wirtualnych, polega wlasnie na tym, ze program w momencie kompilacji
i linkowania _nie wie_, ktore metody beda mu potrzebne. Inna sprawa ze
zwyklymi metodami.
-------
T.2.12 Ciekawostki z historii C++.
Autorem C++ jest Bjarne Stroustrup. W swojej ksiazce "The Design and
Evolution of C++" skladajac wyrazy holdu za wplyw na powstanie jezyka C++,
Stroustrup wymienia m.in. nastepujace osoby: Briana Kernighana, Andrew
Koeniga, Douga McIlroya, Jonathana Shopiro. Kristen Nygaard (Simula 67)
i Dennis Ritchie (C) zajmuja na tej liscie miejsca szczegolnie eksponowane.
W pazdzierniku 1979 roku istnial 1 uzytkownik C++ (C z klasami),
w pazdzierniku 1981 C++ mial 38 uzytkownikow, w dziesiec lat pozniej -
400 000 osob przyznawalo sie do programowania w C++. A obecnie?
Obecnie trwaja prace nad normalizacja jezyka C++,
prowadzone przez kilka cial standaryzacyjnych.
Standard jest juz zatwierdzony,
i mozna go zakupic bezposrednio w ANSI.
Bjarne Stroustrup od cwiercwiecza interesuje sie filozofia i historia.
Jego sympatie do empirystow i awersja do idealistow, "uszczesliwiajacych"
ludzkosc "tym, co dla niej dobre" (slowa Stroustrupa), wplynely na
niektore decyzje i rozwiazania projektowe w C++.
-------
T.2.13 Stosowac wskaznik czy referencje?
Istnieja zasadnicze roznice miedzy wskaznikiem, a referencja:
1. Referencje nie moga byc puste
2. Raz ustawionej referencji nie mozna przeniesc na inny obiek
3. Nie mozna zrobic referencji do referencji, tak jak robi sie
wskaznik do wskaznika.
Generalnie, lepiej jest stosowac referencje. Jednakze jezeli z wyzej
wymienionych powodow jest to niemozliwe, to nalezy zastosowac
wskaznik.
-------
T.2.14 Co to sa sprytne wskazniki (smart pointers)?
Jest to szczegolny rodzaj klas, ktore definiuja operator rzutowania
na typ pierwotny (ktory opakowuja). Z tego powodu moga byc stosowane
w programie tak, jakby byly typu pierwotnego. Najbardziej znane
przyklady sprytnych wskaznikow to string (opakowujacy wskaznik do
char) i auto_ptr (szablon parametryzowany opakowywanym typem) ze
standradowej biblioteki C++.
-------
T.2.15 Czy wszystkie metody w mojej klasie powinny byc wirtualne?
W zasadzie tak. Deklarujac metode jako niewirtualna uniemozliwiasz
zmiane jej implementacji w klasie dziedziczacej, a tym samym zawezasz
elastycznosc swojego systemu.
Jednakze w przypadku metod prostych, np. jedynie zwracajacych
referencje do atrybutu, lepiej zrobic je inline, a metoda inline nie
moze byc wirtualna.
-------
T.2.16 Czy konstruktory moga byc wirtualne?
Nie. Ale mozna stworzyc odpowiednik konstruktora wirtualnego. Opisuje
to wzorzec Abstract Factory z ksiazki "Design Patterns", Gamma et al.
-------
T.2.17 Jak tworzyc klasy abstrakcyjne?
Klasa abstrakcyjna jest kazda klasa, ktora ma choc jedna metode
czysto wirtualna (abstrakcyjna), czyli zadeklarowana, a nie
zaimplementowana. Mozna klase uczynic abstrakcyjna takze deklarujac
wszystkie jej konstruktory jako prywatne lub chronione (protected).
---------------------------------------------------------------------------
-----
T.3.1 Czy jest dostepna darmowa implementacja Smalltalka?
Tak - w ramach GNU. Znalezc go mozna w wiekszosci katalogow z GNU.
-----
T.3.2 Czy SmallTalk jest dobry w praktyce, czy tylko w teorii?
W przypadku Smalltalka o teorii mogla byc mowa jakies 10 lat temu. Teraz
jest to praktyka. Niejaki Dave Thomas z Kanady odpowiedzial na to
pytanie w bardzo ciekawym referacie. Oto, co wdrozono na Smalltalku:
1. Centrale telefoniczna dla kilkudziesieciotysiecznego miasta.
2. "Zastosowania specjalne".
3. IBM zatrudnil ostatnio (pocz.'94) okolo 300 programistow w Smalltalku.
Chyba nie do podlewania kwiatkow.
4. System analizy jakosci programow napisanych w C.
Tyle pamietam. Inna sprawa, ze Smalltalk nie dorownuje C++
rozpowszechnieniu, wiec i produkty komercyjne nie sa tak czeste. Ja nie
potrafie podac zadnych, ale w C++ to chyba tez tylko te, w ktorych
pisaniu sam uczestniczylem.
Czytalem, ze zrobienie jednej klasy w Smalltalku zajmuje 1 osobodni, w
C++ trzy razy tyle. Oczywiscie slyszalem to od entuzjastki Smalltalka,
wiec trzeba wziac poprawke.
-----
T.3.3 Gdzie mozna dowiedziec sie o jezyku Smalltalk i jego zastosowaniach?
Pod nastepujacym adresem:
http://www.stic.org
Jest to adres Smalltalk Industry Council, instytucji zrzeszajacej
firmy produkujace oprogramowanie i narzedzia do Smalltalka. Pod tym
adresem znalezc mozna liste dostepnych kompilatorow (komercyjnych i
darmowych), firmy produkujace biblioteki i narzedzia, materialy do
nauki Smalltalka, informacje o wybranych projektach wykonanych przy
pomocy Smalltalka oraz porownanie sprawnosci Smalltalka z jezykami C i
C++.
---------------------------------------------------------------------------
-----
T.4.1 Jak powinienem zabrac sie za programowanie obiektowe?
Wykonac analize i projekt. Wybrac jezyk i zaimplementowac projekt.
Na poczatek doradzam kilka niewielkich projektow.
Nie zaszkodzi poczytac o analizie, projektowaniu i programowaniu
obiektowym.
-----
T.4.2 Czy OOP oznacza brak optymalizacji?
Ani tak, ani nie - zaden jezyk z gory nie zaklada braku optymalizacji. To
zalezy tylko i wylacznie od konkretnego programu.
-----
T.4.3 Jak rozpoznawac, czy dany program lub projekt jest dobry ?
Mozliwe kryteria:
o dziala - dobrze, nie dziala - zle
o stopien realizacji obiektow jako "czarnych skrzynek"
o zbyt mala lub zbyt duza wiedza klas
o czytelnosc
o podatnosc na zmiany
o powiazania miedzy modulami
o mozliwosc powtornego uzycia
-----
T.4.4 Poszukuje informacji na temat rozszerzen do jezykow obiektowych
(C++, Smalltalk, Eiffel), takich jak np. O++ do C++
O++ jest rozszerzeniem C++ pozwalajacym na tworzenie obiektow
trwalych (persistent), manipulowanie nimi, laczenie w clustery etc.
Jesli chodzi o Smalltalk, to jego rozszerzeniem jesli silnie stypizowany
Strongtalk.
---------------------------------------------------------------------------
end of pl.comp.object FAQ and Summary
---------------------------------------------------------------------------
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: SasQ
Date: Thu, 22 Feb 2007 19:14
Date: Thu, 22 Feb 2007 19:14
122 lines
5909 bytes
5909 bytes
Dnia Fri, 15 Dec 2006 17:10:05 +0000, Kamil Konieczny napisał(a):
> T.2.4 Jak w C++ obsluguje sie funkcje ze zmienna liczba parametrow?
>
> W starym C stosowalo sie <varargs.h>, w nowym (ANSI C oraz C++)
> stosuje sie <stdarg.h>
Jeśli mowa o C++, to chyba raczej <cstdarg>
> void main()
Jeśli przykład był dla C++, to raczej int main().
Standard ANSI/ISO C++ nie dopuszcza void dla main.
> T.2.6 Czy stosowanie zaprzyjazniania klas nalezy do dobrej
> praktyki rogramisty?
>
> Nie, gdyz dopuszcza do latwego dostepu do pol prywatnych i
> chronionych.
Ale nie każdemu ;) Tylko wybranym.
Przyjaźń wcale nie jest "zamachem na enkapsulację", bo klasa
deklarująca przyjaźń sama decyduje o tym, z kim się przyjaźni
i robi to z pełną świadomością ;) Poza tym jeśli już jest
deklaracja przyjaźni, to jest ona częścią interfejsu klasy i
daje sygnał, że dwie klasy są ze sobą ściśle powiązane i
działają wspólnie.
> T.2.9 Co to jest konstruktor kopiujacy?
>
> Konstruktor kopiujacy jest bardzo podobny do operatora przypisania,
> tyle ze o ile operator przypisania uzywany jest dla obiektow juz
> istniejacych, to konstruktor kopiujacy gdy tworzymy nowy obiekt i
> jednoczesnie nadajemy mu jakas wartosc. Przyklad (bo bez przykladu
> raczej malo kto zrozumie :-) ):
Czemu? Po prostu chodzi o zwyczajną inicjalizację nowo tworzonego
biektu wartością innego obiektu tego samego typu ;)
> main()
A typ wartości zwracanej to zjadł pies? :P
> A d; // A tutaj operator przypisania z tym samym argumentem
Raczej linijkę niżej ;) o tu:
> d=b;
> Konstruktor kopiujacy jest tylko i wylacznie wtedy gdy
> przypisanie nastepuje rownoczesnie z utworzeniem.
Ale wtedy to nie jest przypisanie, tylko inicjalizacja ;P
Przypisuje się do obiektów już skonstruowanych.
Jak nie łapiesz różnicy, to spróbuj z obiektami const:
można je tylko inicjalizować, ale nie można do nich już
później przypisywać.
> Dlaczego to wyroznienie? Pozwala to zaoszczedzic operacji,
> bo oczywiscie moglo by byc i tak ze kazda instrukcja typu
> "A b=c;" bylaby rozbijana na dwie: "A b; b=c;".
Tu akurat nie to jest najważniejsze ;)
Ponownie polecam popróbować z const ;)
Jeśli obiekt jest const, nie możesz do niego już nic przypisać
po utworzeniu. Jeśli chcesz ustawić wartość obiektu stałego
"na wzór" innego obiektu, to jedyny moment, gdzie jest to możliwe,
jest przy konstruowaniu. Później jest już "po ptokach" :P
I tu się właśnie przydaje konstruktor kopiujący, zwany też
"inicjalizatorem kopiującym" ;J
> Ale wtedy niepotrzebnie obiekt "b" bylby dwa razy inicjowany
Inicjuje się czynności. Obiekty się inicjalizuje.
I nie słuchaj słownika Kopalińskiego, jego autorzy nie wiedzą
co to jest programowanie ;)
> Najbardziej znane przyklady sprytnych wskaznikow to string
> (opakowujacy wskaznik do char)
?? :P
Tak rozumując, to każda klasa, która zawierałaby w swojej
implementacji jakieś wskaźniki i je obsługiwała, musiałaby
być "sprytnym wskaźnikiem" :P Ja bym raczej zawęził ten termin
do obiektów "symulujących" zwykłe wskaźniki w widoczny sposób.
> Opisuje to wzorzec Abstract Factory z ksiazki "Design
> Patterns", Gamma et al.
"et al." to skrót od łacińskiego "et alii" = "i inni" ;J
> Klasa abstrakcyjna jest kazda klasa, ktora ma choc jedna metode
> czysto wirtualna (abstrakcyjna), czyli zadeklarowana, a nie
> zaimplementowana. Mozna klase uczynic abstrakcyjna takze deklarujac
> wszystkie jej konstruktory jako prywatne lub chronione (protected).
No nie wiem ;J
Uczynienie konstruktora prywatnym lub chronionym jeszcze nie
czyni klasy abstrakcyjną, bo obiekty tej klasy wbrew pozorom
nadal mogą być tworzone, tylko nie każdemu wolno to robić ;J
Jeśli konstruktor jest private, to wolno tworzyć obiekt tylko
z wnętrza klasy, a jeśli protected, to dodatkowo z wnętrza
klas pochodnych. Klasa "dla samej siebie" albo "dla siebie i
rodzinki" nie jest już wtedy wcale abstrakcyjna. Podobnie
jeśli klasa ma prywatny konstruktor, ale przyjaźni się z
jakąś funkcją która może ten konstruktor prywatny wtedy wywołać
i utworzyć obiekty tej klasy, to klasa już nie może być traktowana
jako abstrakcyjna :P
Dlatego zawęziłbym tą definicję tylko dla klas, które mają
choć jedną metodę czysto wirtualną, bo tylko to daje pełną
gwarancję, że nie powstanie żaden obiekt tej klasy, choćby i
na jej własny użytek prywatny ;J
Klasa Ssak jest dobrym przykładem klasy abstrakcyjnej. Jeśli
chciałbyś ją uzyskać ukrywając konstruktor, to nadal klasa może
stworzyć instancję Ssaka :P [np. z metody statycznej albo
zaprzyjaźnionej] i co wtedy? :D Widziałeś kiedy ssaka luzem? ;)
P.S.: chodziłem z jednym Kamilem Koniecznym do podstawówki :J
Może to ty? :D Jesteś może z Żywca? ;J
--
SasQ
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: rwt
Date: Thu, 22 Feb 2007 22:29
Date: Thu, 22 Feb 2007 22:29
74 lines
3630 bytes
3630 bytes
Odpowiedź do listu Wielce Szanownej Pani / Szanownego Pana ‹SasQ›. Wysłannik wyższej inteligencji tako rzecze :): >> T.2.9 Co to jest konstruktor kopiujacy? >> Konstruktor kopiujacy jest bardzo podobny do operatora przypisania, >> tyle ze o ile operator przypisania uzywany jest dla obiektow juz >> istniejacych, to konstruktor kopiujacy gdy tworzymy nowy obiekt i >> jednoczesnie nadajemy mu jakas wartosc. Przyklad (bo bez przykladu >> raczej malo kto zrozumie :-) ): > Czemu? Po prostu chodzi o zwyczajną inicjalizację nowo tworzonego > biektu wartością innego obiektu tego samego typu ;) >> A d; // A tutaj operator przypisania z tym samym argumentem > Raczej linijkę niżej ;) o tu: >> d=b; >> Konstruktor kopiujacy jest tylko i wylacznie wtedy gdy >> przypisanie nastepuje rownoczesnie z utworzeniem. > Ale wtedy to nie jest przypisanie, tylko inicjalizacja ;P > Przypisuje się do obiektów już skonstruowanych. > Jak nie łapiesz różnicy, to spróbuj z obiektami const: > można je tylko inicjalizować, ale nie można do nich już > później przypisywać. >> Dlaczego to wyroznienie? Pozwala to zaoszczedzic operacji, >> bo oczywiscie moglo by byc i tak ze kazda instrukcja typu >> "A b=c;" bylaby rozbijana na dwie: "A b; b=c;". > Tu akurat nie to jest najważniejsze ;) > Ponownie polecam popróbować z const ;) > Jeśli obiekt jest const, nie możesz do niego już nic przypisać > po utworzeniu. Jeśli chcesz ustawić wartość obiektu stałego > "na wzór" innego obiektu, to jedyny moment, gdzie jest to możliwe, > jest przy konstruowaniu. Później jest już "po ptokach" :P > I tu się właśnie przydaje konstruktor kopiujący, zwany też > "inicjalizatorem kopiującym" ;J >> Ale wtedy niepotrzebnie obiekt "b" bylby dwa razy inicjowany > Inicjuje się czynności. Obiekty się inicjalizuje. > I nie słuchaj słownika Kopalińskiego, jego autorzy nie wiedzą > co to jest programowanie ;) >> Najbardziej znane przyklady sprytnych wskaznikow to string >> (opakowujacy wskaznik do char) > ?? :P > Tak rozumując, to każda klasa, która zawierałaby w swojej > implementacji jakieś wskaźniki i je obsługiwała, musiałaby > być "sprytnym wskaźnikiem" :P Ja bym raczej zawęził ten termin > do obiektów "symulujących" zwykłe wskaźniki w widoczny sposób. Można by zauważyć, że dla zmiennych typu klasa nie zachodzą przypisania. Tak naprawdę dla nich są tylko inicjalizacje. Natomiast przypisania pozostały dla zmiennych prymitywnych oraz referencji, wskaźników. Wasz -- / qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!Gn@8're. w8in/ad \ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh / | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee L o_O http://tech.groups.yahoo.com/group/opRWTng O_o L"EnOF"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 26 Feb 2007 08:58
Date: Mon, 26 Feb 2007 08:58
33 lines
2175 bytes
2175 bytes
rwt wrote: > Odpowiedź do listu Wielce Szanownej Pani / Szanownego Pana ?SasQ?. > Wysłannik wyższej inteligencji tako rzecze :): > >>> T.2.9 Co to jest konstruktor kopiujacy? > >>> Konstruktor kopiujacy jest bardzo podobny do operatora przypisania, >>> tyle ze o ile operator przypisania uzywany jest dla obiektow juz >>> istniejacych, to konstruktor kopiujacy gdy tworzymy nowy obiekt i >>> jednoczesnie nadajemy mu jakas wartosc. Przyklad (bo bez przykladu >>> raczej malo kto zrozumie :-) ): > >> Czemu? Po prostu chodzi o zwyczajną inicjalizację nowo tworzonego >> biektu wartością innego obiektu tego samego typu ;) (...) > > Można by zauważyć, że dla zmiennych typu klasa nie zachodzą > przypisania. Tak naprawdę dla nich są tylko inicjalizacje. Natomiast > przypisania pozostały dla zmiennych prymitywnych oraz referencji, > wskaźników. Pomimo, źe dość uważnie przeczytałem komentarz SasQ, nie bardzo rozumiem Twoją odpowiedź. Czy mógłbyś to nieco rozwinąć? No i pytanie podstawowe: dlaczego uważasz, że dla obiektów nie występują tutaj przypisania a jedynie "przypisania (...) dla zmiennych prymitywnych"? Przypominam, że mowa jest o C++ a nie jakimś zorientowanym na referencje języku jak Java czy Python. -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: rwt
Date: Mon, 26 Feb 2007 19:10
Date: Mon, 26 Feb 2007 19:10
49 lines
3115 bytes
3115 bytes
Odpowiedź do listu Wielce Szanownej Pani / Szanownego Pana ‹Mariusz Lotko›. Wysłannik wyższej inteligencji tako rzecze :): > rwt wrote: >> Odpowiedź do listu Wielce Szanownej Pani / Szanownego Pana ?SasQ?. >> Wysłannik wyższej inteligencji tako rzecze :): >>>> T.2.9 Co to jest konstruktor kopiujacy? >>>> Konstruktor kopiujacy jest bardzo podobny do operatora przypisania, >>>> tyle ze o ile operator przypisania uzywany jest dla obiektow juz >>>> istniejacych, to konstruktor kopiujacy gdy tworzymy nowy obiekt i >>>> jednoczesnie nadajemy mu jakas wartosc. Przyklad (bo bez przykladu >>>> raczej malo kto zrozumie :-) ): >>> Czemu? Po prostu chodzi o zwyczajną inicjalizację nowo tworzonego >>> biektu wartością innego obiektu tego samego typu ;) > (...) >> Można by zauważyć, że dla zmiennych typu klasa nie zachodzą >> przypisania. Tak naprawdę dla nich są tylko inicjalizacje. Natomiast >> przypisania pozostały dla zmiennych prymitywnych oraz referencji, >> wskaźników. > Pomimo, źe dość uważnie przeczytałem komentarz SasQ, nie bardzo > rozumiem Twoją odpowiedź. Czy mógłbyś to nieco rozwinąć? No i > pytanie podstawowe: dlaczego uważasz, że dla obiektów nie występują > tutaj przypisania a jedynie "przypisania (...) dla zmiennych > prymitywnych"? Przypominam, że mowa jest o C++ a nie jakimś > zorientowanym na referencje języku jak Java czy Python. Być może w języku nadal pozostaje operator przypisania (jak we wcześniejszym cytacie), ale… obiekty, które mają program wiążący z mechanizmami języka, inny niż zformalizowany, czyli inny niż otwarty mimo że istniejący (jak w językach funkcyjnych)— po zwykłym skopiowaniu wartości przez sam związek z innymi obiektami tworzony przez ten program stają się klonami a nie kopiami. Oczywiście jeszcze innego rodzaju operacją jest ‚przypisanie’ do zmiennej typu klasy dziedziczącej dany typ. Mimo że do wszystkiego używa się tego samego operatora. Wasz -- / qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!Gn@8're. w8in/ad \ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh / | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee L o_O http://tech.groups.yahoo.com/group/opRWTng O_o L"EnOF"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: SasQ
Date: Mon, 26 Feb 2007 21:12
Date: Mon, 26 Feb 2007 21:12
76 lines
4438 bytes
4438 bytes
Dnia Mon, 26 Feb 2007 20:10:02 +0100, rwt napisał(a):
> Być może w języku nadal pozostaje operator przypisania (jak we
> wcześniejszym cytacie), ale... obiekty, które mają program wiążący
> z mechanizmami języka, inny niż zformalizowany, czyli inny niż
> otwarty mimo że istniejący (jak w językach funkcyjnych)- po
> zwykłym skopiowaniu wartości przez sam związek z innymi obiektami
> tworzony przez ten program stają się klonami a nie kopiami.
Atak klonów ;)
Przyznam że ja też nie zrozumiałem poprzednio, a to "wyjaśnienie"
jeszcze bardziej mi zamieszało i nic z tego nie rozumiem :P
Ponieważ w programowaniu liczy się precyzja, pozwolę sobie
zadać kilka pytań o słownictwo, którego używasz, byśmy się
dobrze rozumieli i posługiwali się tymi samymi definicjami:
1) Co to są "zmienne typu klasa"?
Moje definicje użytych tutaj słów przedstawiają się tak:
zmienna: typ obiektu, który może zmieniać swój stan.
stała: typ obiektu, który nie może zmieniać swojego stanu.
stan: wartość ;)
obiekt: wydzielony jednolity i ciągły obszar pamięci, który
ma jasno określony typ.
typ: określa jakie wartości/stany może przyjmować obiekt,
jak te stany mogą się zmieniać, oraz jakie operacje
można na tym obiekcie wykonywać
klasa: definiuje nowy typ obiektu
2) Dlaczego miałyby nie zachodzić dla nich przypisania?
Moja definicja przypisania:
Skopiowanie stanu [wartości] jednego obiektu do drugiego,
zastępując poprzednią wartość obiektu docelowego.
3) Czemu dla nich miałyby być tylko inicjalizacje?
Moja definicja inicjalizacji:
Nadanie początkowej wartości obiektowi w momencie jego
utworzenia [można to zrobić tylko wtedy].
4) Co to są zmienne prymitywne?
Czy chodziło ci może o zmienne [lub w ogólności obiekty]
typów wbudowanych?
Typy wbudowane: istniejące w języku od początku, nie
definiowane przez użytkownika.
5) Dlaczegóż to tylko dla nich pozostają przypisania?
6) "Być może w języku nadal pozostaje operator przypisania"
Mówisz tutaj o operatorze przypisania dla jakiego typu?
Jednego z typów wbudowanych? Bo nie wiem jak inaczej
zrozumieć że on "pozostaje w języku".
7) "obiekty, które mają program wiążący z mechanizmami języka,
inny niż zformalizowany, czyli inny niż otwarty"
Co to jest "program wiążący z mechanizmami języka"?
A co to jest "program sformalizowany" czy "program otwarty"?
[o ile dobrze zrozumiałem sens logiczny tego zdania :P]
8) "mimo że istniejący (jak w językach funkcyjnych)- po zwykłym
skopiowaniu wartości przez sam związek z innymi obiektami
tworzony przez ten program"
Tego to już nijak nie potrafię ugryźć :| Nawet nie wiem o co
zapytać, bo zupełnie nie jarzę sensu tego zdania :7
9) "stają się klonami a nie kopiami"
Czym się różni kopia od klonu?
10) "Oczywiście jeszcze innego rodzaju operacją jest 'przypisanie'
do zmiennej typu klasy dziedziczącej dany typ."
Co to jest "zmienna typu klasy dziedziczącej dany typ"? :P
11) "Mimo że do wszystkiego używa się tego samego operatora."
Czyli do czego, i jakiego operatora? Bo z kontekstu tego nie
mogę wyczytać...
--
SasQ
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: rwt
Date: Mon, 26 Feb 2007 21:29
Date: Mon, 26 Feb 2007 21:29
9 lines
1176 bytes
1176 bytes
Che, che. Pełna analiza. Wasz -- / qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!Gn@8're. w8in/ad \ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh / | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee L o_O http://tech.groups.yahoo.com/group/opRWTng O_o L"EnOF"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 26 Feb 2007 22:55
Date: Mon, 26 Feb 2007 22:55
8 lines
1100 bytes
1100 bytes
rwt wrote: > Che, che. Pełna analiza. Wygląda to raczej na atak trolli niż atak klonów :-) -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: SasQ
Date: Mon, 26 Feb 2007 23:02
Date: Mon, 26 Feb 2007 23:02
14 lines
1521 bytes
1521 bytes
Dnia Mon, 26 Feb 2007 23:55:29 +0100, Mariusz Lotko napisał(a): > rwt wrote: > >> Che, che. Pełna analiza. > > Wygląda to raczej na atak trolli niż atak klonów :-) A może bot spamerski? :) Ostatnio pojawiły się takie, co biorą słownik z danej dziedziny i generują losowe zestawienia słów, przypominające normalny tekst ;) -- SasQ
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Piotr Dembiński
Date: Wed, 28 Feb 2007 14:32
Date: Wed, 28 Feb 2007 14:32
15 lines
1602 bytes
1602 bytes
SasQ <sasq1@go2.pl> writes: > Dnia Mon, 26 Feb 2007 23:55:29 +0100, Mariusz Lotko napisał(a): > >> rwt wrote: >> >>> Che, che. Pełna analiza. >> >> Wygląda to raczej na atak trolli niż atak klonów :-) > > A może bot spamerski? :) Ostatnio pojawiły się takie, co biorą > słownik z danej dziedziny i generują losowe zestawienia słów, > przypominające normalny tekst ;) Ano są: http://pdos.csail.mit.edu/scigen/.
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Thu, 01 Mar 2007 10:51
Date: Thu, 01 Mar 2007 10:51
95 lines
5456 bytes
5456 bytes
Dnia Mon, 26 Feb 2007 22:12:45 +0100, SasQ skrobie: > Dnia Mon, 26 Feb 2007 20:10:02 +0100, rwt napisał(a): > > Być może w języku nadal pozostaje operator przypisania (jak we > > wcześniejszym cytacie), ale... obiekty, które mają program wiążący > > z mechanizmami języka, inny niż zformalizowany, czyli inny niż > > otwarty mimo że istniejący (jak w językach funkcyjnych)- po > > zwykłym skopiowaniu wartości przez sam związek z innymi obiektami > > tworzony przez ten program stają się klonami a nie kopiami. > Atak klonów ;) Nie ma się co śmiać. Kopiowanie nie zachodzi dla obiektów typów niewartościowych, a jedynie dla obiektów typów wartościowych. Kopiowaniu podlega wtedy owa "wartość", która może być dowolnie przenoszona pomiędzy poszczególnymi obiektami. Natomiast obiekty niewartościowe, jak sama nazwa wskazuje, wartości nie mają, więc one podlegają klonowaniu - tworzy się nowy obiekt o nowej tożsamości. W obiektach wartościowych tożsamością jest wartość. > Przyznam że ja też nie zrozumiałem poprzednio, a to "wyjaśnienie" > jeszcze bardziej mi zamieszało i nic z tego nie rozumiem :P > Ponieważ w programowaniu liczy się precyzja, pozwolę sobie > zadać kilka pytań o słownictwo, którego używasz, byśmy się > dobrze rozumieli i posługiwali się tymi samymi definicjami: > 1) Co to są "zmienne typu klasa"? > Moje definicje użytych tutaj słów przedstawiają się tak: > zmienna: typ obiektu, który może zmieniać swój stan. > stała: typ obiektu, który nie może zmieniać swojego stanu. > stan: wartość ;) Dokładnie to bieżąca wartość, w przypadku typów wartościowych. W pozostałych będzie to zespół wszystkich wartości składowych obiektu (jeśli składową jest obiekt, to jeszcze i jego wartości itd.) > obiekt: wydzielony jednolity i ciągły obszar pamięci, który > ma jasno określony typ. > typ: określa jakie wartości/stany może przyjmować obiekt, > jak te stany mogą się zmieniać, oraz jakie operacje > można na tym obiekcie wykonywać > klasa: definiuje nowy typ obiektu > 2) Dlaczego miałyby nie zachodzić dla nich przypisania? > Moja definicja przypisania: > Skopiowanie stanu [wartości] jednego obiektu do drugiego, > zastępując poprzednią wartość obiektu docelowego. Słusznie, pod warunkiem, że to jest obiekt wartościowy. > 3) Czemu dla nich miałyby być tylko inicjalizacje? > Moja definicja inicjalizacji: > Nadanie początkowej wartości obiektowi w momencie jego > utworzenia [można to zrobić tylko wtedy]. Znów - w przypadku typów wartościowych. W pozostałych jest to po prostu inicjalizacja składowych - a dalej już jak wyżej. > 4) Co to są zmienne prymitywne? > Czy chodziło ci może o zmienne [lub w ogólności obiekty] > typów wbudowanych? > Typy wbudowane: istniejące w języku od początku, nie > definiowane przez użytkownika. Kwestia czy to są typy wbudowane, czy nie, zależy od języka. W Javie np. nie ma innych typów wartościowych niż wbudowane - plus referencje, przy czym wartością zmiennej referencyjnej jest referencja do określonego obiektu (lub null). W C++ możemy sobie dowolnie tworzyć typy wartościowe. > 5) Dlaczegóż to tylko dla nich pozostają przypisania? Dla typów wartościowych. > 6) "Być może w języku nadal pozostaje operator przypisania" > Mówisz tutaj o operatorze przypisania dla jakiego typu? > Jednego z typów wbudowanych? Bo nie wiem jak inaczej > zrozumieć że on "pozostaje w języku". Też nie rozumiem ;) > 9) "stają się klonami a nie kopiami" > Czym się różni kopia od klonu? Tym właśnie, że sklonowany obiekt staje się osobnym obiektem z własnym zestawem stanów. Obiekty wartościowe mają określoną tożsamość przez wartość, więc po wykonaniu a = b, 'a' staje się "tym samym" co b - dopóki ktoś nie przypisze mu innej wartości. -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: rwt
Date: Fri, 02 Mar 2007 08:26
Date: Fri, 02 Mar 2007 08:26
19 lines
1591 bytes
1591 bytes
Odpowiedź do listu Wielce Szanownej Pani / Szanownego Pana ‹Mariusz Lotko›. Wysłannik wyższej inteligencji tako rzecze :): > rwt wrote: >> Che, che. Pełna analiza. > Wygląda to raczej na atak trolli niż atak klonów :-) Zrozumiałeś, o czym pisałem, czy wypowiadasz się, by zaistnieć? Nie ukrywam, że odpowiedź lub jej brak zadecyje o ignorowaniu. Wasz -- / qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!Gn@8're. w8in/ad \ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh / | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee L o_O http://tech.groups.yahoo.com/group/opRWTng O_o L"EnOF"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Sat, 03 Mar 2007 11:19
Date: Sat, 03 Mar 2007 11:19
18 lines
1515 bytes
1515 bytes
rwt wrote: >>> Che, che. Pełna analiza. > >> Wygląda to raczej na atak trolli niż atak klonów :-) > > Zrozumiałeś, o czym pisałem, czy wypowiadasz się, by zaistnieć? > Nie ukrywam, że odpowiedź lub jej brak zadecyje o ignorowaniu. Ignoruj. Czy Twoja "wypowiedź" (patrz piersza linijka) zasługuje na coś więcej? A co do "zaistnienia" - to nie ja wymyślam niestworzone teorie na temat rzeczy prostych i zrozumiałych. -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Sat, 03 Mar 2007 11:26
Date: Sat, 03 Mar 2007 11:26
30 lines
2281 bytes
2281 bytes
Sektor van Skijlen wrote: > Dnia Mon, 26 Feb 2007 22:12:45 +0100, SasQ skrobie: >> Dnia Mon, 26 Feb 2007 20:10:02 +0100, rwt napisał(a): > >> > Być może w języku nadal pozostaje operator przypisania (jak we >> > wcześniejszym cytacie), ale... obiekty, które mają program wiążący >> > z mechanizmami języka, inny niż zformalizowany, czyli inny niż >> > otwarty mimo że istniejący (jak w językach funkcyjnych)- po >> > zwykłym skopiowaniu wartości przez sam związek z innymi obiektami >> > tworzony przez ten program stają się klonami a nie kopiami. > >> Atak klonów ;) > > Nie ma się co śmiać. > > Kopiowanie nie zachodzi dla obiektów typów niewartościowych, a jedynie dla > obiektów typów wartościowych. Kopiowaniu podlega wtedy owa "wartość", > która może być dowolnie przenoszona pomiędzy poszczególnymi obiektami. > > Natomiast obiekty niewartościowe, jak sama nazwa wskazuje, wartości nie > mają, więc one podlegają klonowaniu - tworzy się nowy obiekt o nowej > tożsamości. W obiektach wartościowych tożsamością jest wartość. Czy możesz podać jakieś źródła mówiące o typach wartościowych i niewartościowych? Google na takie pytanie odpowiada wyłącznie Twoimi postami z usenetu. -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Sat, 03 Mar 2007 14:03
Date: Sat, 03 Mar 2007 14:03
78 lines
5786 bytes
5786 bytes
Dnia Sat, 03 Mar 2007 12:26:28 +0100, Mariusz Lotko skrobie: > Czy możesz podać jakieś źródła mówiące o typach wartościowych i > niewartościowych? Google na takie pytanie odpowiada wyłącznie Twoimi > postami z usenetu. Problem w tym, że wiedza na ten temat jest aktualnie na etapie "odkrywamy, że w języku nagle jest coś, czego twórca nie wymyślił". Natomiast tak dokładniej sprawa polega na tym, że o istnieniu wartości od dłuższego czasu wszyscy wiedzieli, tylko że nie bardzo wiedzieli, jak się mają do tego zabrać. Przykładowo, od zawsze wiedziano, że takie 'int' i 'Car' różni coś więcej, niż tylko zestaw dozwolonych operacji. Ale w większości języków niestety sprowadzono to do specjalnego traktowania liczb całkowitych (tak jest w Smalltalku i w Javie), a co za tym idzie, uniemożliwiono tworzenie własnych typów wartościowych. W Javie po prostu stwierdzono, że wszystkie typy wartościowe to będą typy wbudowane (czyli, najprościej mówiąc, są to wszystkie rzeczy, których nie tworzy się przez new) i użytkownik nie może definiować własnych. Tematem się raczej nikt nie zajął i raczej nikt go nie opracował - wiedziałbym o tym, bo po takim wałkowaniu tematu, jakie zorganizowałem na pl.comp.lang.c, myślę że ktoś dobrze obyty z ogólnie dostępną wiedzą nt. informatyki już by to zgłosił. Może nikt nie uważa go za wart uwagi. Co jeszcze ciekawsze, większość języków (nie tylko Smalltalk i Java, ale również wiele funkcjonalnych) ma dziwnie "uniwersalne" podejście do tych obiektów i usiłuje zaciemnić ten podział. W Smalltalku przykładowo (a także np. w OCamlu) masz każdy obiekt zapisany na czterech bajtach. W tych czterech bajtach są jednak wyznaczone odpowiednie bity, które odróżniają liczbę całkowitą od wskaźnika na obiekt. W ten sposób liczba całkowita jest takim samym obiektem, jak każdy inny, a fakt, że nie następuje przydział pamięci przy tworzeniu, jest szczegółem implementacyjnym. Jednak podział na "wartości" i "obiekty" bierze się nie z samej konstrukcji języków, tylko z pojęć używanych również w codziennym życiu. Wszystko zależy od tego, co oznacza dla nas stwierdzenie "ten sam". Przykładowo, jeśli mówimy "ten sam samochód", to chodzi nam o ten sam egzemplarz samochodu, a nie o inny samochód tylko identyczny. Jeśli mówimy "ten sam kolor" albo "ten sam producent" (!) - chodzi o to, że samochód został pomalowany farbą o tym samym kodzie koloru, a w drugim przypadku, że identyfikator producenta jest identyczny. Identyfikator i kolor nie mogą mieć egzemplarzy, więc to są wartości. Identyfikator akurat dodatkowo obrazuje nam coś, co jest odpowiednikiem "referencji", która też jest typem wartościowym. Z podziałem na typy wartościowe i niewartościowe wiąże się również kwestia porównywania, nie tylko kopiowania.Przykładowo, porównywanie powinno się odbywać tylko dla typów wartościowych, a to powinno konkretnie stwierdzić, czy oba obiekty posiadają tą samą wartość. Porównanie obiektów typów niewartościowych nie ma sensu - albo uznajemy go za obiekt wartościowy (tzn. taki, gdzie kopiowanie z innego czyni go identycznym z tym innym), albo niewartościowy, więc nie ma tu czego porównać. Niestety języki próbujące iść w poprzek tego podziału dostają nadmiernej komplikacji. Nie pamiętam nawet dokładnie, jakie języki to mają, ale jest ich wiele. Chodzi o osobne wręcz operatory do porównania osobno wartości i tożsamości - i tu mamy wiele różnych kombinacji, jak <> i != (dla nierównych), czasem jest = i == itd. Muszą być wprowadzone, bo sam język nie rozróżnia typów obiektowych i wartościowych. Programista zwykle rozróżnia, nawet bezwiednie, ale i tak teoretycznie da się zrobić taką głupotę, jak obiekt wartościowy z własną tożsamością. Ale tu ciekawostka - Java np. nie posiada takiego rozróżnienia i to jest w niej pozytywne. Problem z Javą jednak leży gdzie indziej - jej typ String jest typem obiektowym, a nie wartościowym (podczas gdy String moim zdaniem należy właśnie do typów wartościowych i takim jest np. w C++). -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Marcin 'Qrczak' Kowalczyk
Date: Sat, 03 Mar 2007 16:45
Date: Sat, 03 Mar 2007 16:45
18 lines
1982 bytes
1982 bytes
Dnia 03-03-2007, sob o godzinie 14:03 +0000, Sektor van Skijlen
napisał(a):
> Ale w większości języków niestety
> sprowadzono to do specjalnego traktowania liczb całkowitych (tak jest w
> Smalltalku i w Javie), a co za tym idzie, uniemożliwiono tworzenie własnych
> typów wartościowych.
Nie ma potrzeby ściślejszego wyróżniania typów wartościowych niż
danie im odpowiedniej definicja równości. W języku, który nie kopiuje
niejawnie obiektów (czyli w większości poza C/C++), jedyne potrzebne
wsparcie dla typów wartościowych to definicja standardowej równości
dla tych typów uwzględniająca zawartość, a nie tożsamość obiektu.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Sat, 03 Mar 2007 17:46
Date: Sat, 03 Mar 2007 17:46
44 lines
3346 bytes
3346 bytes
Dnia Sat, 03 Mar 2007 17:45:39 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 03-03-2007, sob o godzinie 14:03 +0000, Sektor van Skijlen > napisał(a): > > Ale w większości języków niestety > > sprowadzono to do specjalnego traktowania liczb całkowitych (tak jest w > > Smalltalku i w Javie), a co za tym idzie, uniemożliwiono tworzenie własnych > > typów wartościowych. > Nie ma potrzeby ściślejszego wyróżniania typów wartościowych niż > danie im odpowiedniej definicja równości. W języku, który nie kopiuje > niejawnie obiektów (czyli w większości poza C/C++), jedyne potrzebne > wsparcie dla typów wartościowych to definicja standardowej równości > dla tych typów uwzględniająca zawartość, a nie tożsamość obiektu. Możliwe, ale byłbym za tym, żeby po prostu określać, czy porównanie ma porównywać WARTOŚĆ, czy TOŻSAMOŚĆ. Tyle, myślę, by wystarczyło. Chodzi jednak o to, żeby w języku była możliwa do opisania konstrukcja typu: String s; ... s += "\n"; Ja wiem, że Javowy string to wszystko ma (przydałoby mu się tylko, żeby operator porównania też porównywał po wartości), ale co mnie to obchodzi - String jest w Javie dokładnie tak samo typem wbudowanym, jak int. Jako wsparcie dla typów wartościowych, takie pełne, wyobrażałbym sobie: - możliwość określenia, jak wykonuje się porównanie wartości (i opisać to jako standardowe porównanie dla tego typu) - możliwość określenia, co ma się dziać z obiektem, który chcemy zmodyfikować w miejscu za pośrednictwem takiego uchwytu, jaki akurat jest dostępny w języku (w Javie tym uchwytem jest referencja, więc i tak musi się wtedy odbyć wyprodukowanie nowego obiektu i zgubienie starego) -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Sat, 03 Mar 2007 23:56
Date: Sat, 03 Mar 2007 23:56
29 lines
2347 bytes
2347 bytes
Sektor van Skijlen wrote: > Dnia Sat, 03 Mar 2007 17:45:39 +0100, Marcin 'Qrczak' Kowalczyk skrobie: >> Dnia 03-03-2007, sob o godzinie 14:03 +0000, Sektor van Skijlen >> napisał(a): > >> > Ale w większości języków niestety >> > sprowadzono to do specjalnego traktowania liczb całkowitych (tak jest w >> > Smalltalku i w Javie), a co za tym idzie, uniemożliwiono tworzenie >> > własnych typów wartościowych. > >> Nie ma potrzeby ściślejszego wyróżniania typów wartościowych niż >> danie im odpowiedniej definicja równości. W języku, który nie kopiuje >> niejawnie obiektów (czyli w większości poza C/C++), jedyne potrzebne >> wsparcie dla typów wartościowych to definicja standardowej równości >> dla tych typów uwzględniająca zawartość, a nie tożsamość obiektu. > > Możliwe, ale byłbym za tym, żeby po prostu określać, czy porównanie ma > porównywać WARTOŚĆ, czy TOŻSAMOŚĆ. Tyle, myślę, by wystarczyło. Python rozróżnia tożsamość z wartością tzn. są porównania 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? -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Sun, 04 Mar 2007 14:50
Date: Sun, 04 Mar 2007 14:50
37 lines
3122 bytes
3122 bytes
Dnia Sun, 04 Mar 2007 00:56:21 +0100, Mariusz Lotko skrobie: > Sektor van Skijlen wrote: > > Dnia Sat, 03 Mar 2007 17:45:39 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > >> Dnia 03-03-2007, sob o godzinie 14:03 +0000, Sektor van Skijlen > >> napisał(a): > > > >> > Ale w większości języków niestety > >> > sprowadzono to do specjalnego traktowania liczb całkowitych (tak jest w > >> > Smalltalku i w Javie), a co za tym idzie, uniemożliwiono tworzenie > >> > własnych typów wartościowych. > > > >> Nie ma potrzeby ściślejszego wyróżniania typów wartościowych niż > >> danie im odpowiedniej definicja równości. W języku, który nie kopiuje > >> niejawnie obiektów (czyli w większości poza C/C++), jedyne potrzebne > >> wsparcie dla typów wartościowych to definicja standardowej równości > >> dla tych typów uwzględniająca zawartość, a nie tożsamość obiektu. > > > > Możliwe, ale byłbym za tym, żeby po prostu określać, czy porównanie ma > > porównywać WARTOŚĆ, czy TOŻSAMOŚĆ. Tyle, myślę, by wystarczyło. > Python rozróżnia tożsamość z wartością tzn. są porównania > 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ść. -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Adam Karpierz
Date: Sun, 04 Mar 2007 16:30
Date: Sun, 04 Mar 2007 16:30
36 lines
2660 bytes
2660 bytes
"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ść. Czyli chodzi ci ogolnie o to, aby cos bylo sp...dzielone 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 Podobnie z operatorem przypisania Jelsi do skopowiania obiektu uzywa sie tego samego operatora co do przypisania referencji to jest to rowniez syf. 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 Podobnie chodzi o to aby byl dostepny inny operator do 'clone' obiektu a inny do zmiany referencji Porzadne jezyki tak maja (mialy nawet w latach 60-tych), a jesli np ten syf zwany C++ tego nie ma to nazwij to zwyczajnie syfem. i przejdz nad tym do porzadku dziennego, a nie probuj robic z tego syfu kamieni szlachetnych. AK
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Marcin 'Qrczak' Kowalczyk
Date: Sun, 04 Mar 2007 16:46
Date: Sun, 04 Mar 2007 16:46
25 lines
2580 bytes
2580 bytes
Dnia 04-03-2007, nie o godzinie 14:50 +0000, Sektor van Skijlen
napisał(a):
> > 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ść.
To się sprawdza, ale tylko w językach, w których podstawowe wartości są
realizowane przez obiekty immutable. Jeśli tak nie jest, czyli kiedy
typ, który powinien być typem wartościowym, jest realizowany jako obiekt
ze stanem, czyli kiedy ten obiekt ze stanem tak naprawdę modeluje
zmienną tego typu, a nie wartość tego typu, to mamy konflikt: równość
zmiennych powinna porównywać zmienne jako takie, ale częściej chcemy
porównywać bieżące wartości tych zmiennych i to zazwyczaj robi operator
==. Czyli po pierwsze działa niezgodnie z ogólnymi wytycznymi, a po
drugie porównanie zmiennych w razie czego też powinno być dostępne.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Sun, 04 Mar 2007 18:37
Date: Sun, 04 Mar 2007 18:37
89 lines
4514 bytes
4514 bytes
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.
Operator == dla dwóch obiektów powinien _zawsze_ porównywać równość
semantyczną ich _zawartości_, a nie kombinować z ich tożsamością.
Nie widzę szczególnego powodu, żeby wskaźniki nazywać "obiektami
niewartościowymi", skoro pełnią one funkcję referencji, czy jak
kto woli, identyfikatora obiektu.
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.
> Czyli chodzi ci ogolnie o to, aby cos bylo sp...dzielone
Wszystko można zepsuć, jeśli się tylko za mocno kombinuje nie zważając
na intencje twórcy (tu: twórcy C++).
> 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).
> Podobnie z operatorem przypisania
> Jelsi do skopowiania obiektu uzywa sie tego samego
> operatora co do przypisania referencji to jest to rowniez syf.
j.w.
> 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.
> 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++...
>
> Porzadne jezyki tak maja (mialy nawet w latach 60-tych),
> a jesli np ten syf zwany C++ tego nie ma to nazwij to zwyczajnie syfem.
> i przejdz nad tym do porzadku dziennego, a nie probuj robic
> z tego syfu kamieni szlachetnych.
Jako fan C++ nie zgadzam się co do syfu, ale zgadzam się, że dorabianie
teorii tu, gdzie jej nie ma i nie będzie, nie czyni niczego lepszym.
--
Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Adam Karpierz
Date: Sun, 04 Mar 2007 19:52
Date: Sun, 04 Mar 2007 19:52
11 lines
1747 bytes
1747 bytes
"Mariusz Lotko" <imie.nazwisko@wp.pl> wrote: > Adam Karpierz wrote: >>> 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ść. Prosze mi nie przypisywac slow Sekatora :) AK
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Sun, 04 Mar 2007 21:09
Date: Sun, 04 Mar 2007 21:09
52 lines
4271 bytes
4271 bytes
Dnia Sun, 04 Mar 2007 17:46:12 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 04-03-2007, nie o godzinie 14:50 +0000, Sektor van Skijlen > napisał(a): > > > 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ść. > To się sprawdza, ale tylko w językach, w których podstawowe wartości są > realizowane przez obiekty immutable. Jeśli tak nie jest, czyli kiedy > typ, który powinien być typem wartościowym, jest realizowany jako obiekt > ze stanem, czyli kiedy ten obiekt ze stanem tak naprawdę modeluje > zmienną tego typu, a nie wartość tego typu, to mamy konflikt: równość > zmiennych powinna porównywać zmienne jako takie, ale częściej chcemy > porównywać bieżące wartości tych zmiennych i to zazwyczaj robi operator > ==. Czyli po pierwsze działa niezgodnie z ogólnymi wytycznymi, a po > drugie porównanie zmiennych w razie czego też powinno być dostępne. Ha! W razie czego! No właśnie o to chodzi, że nie. Jeśli określamy dany typ jako wartościowy, to tożsamość przechowującego ją obiektu nie powinna nas interesować w ogóle. Jeśli jest to potrzebne do jakichś wewnętrznych operacji, to powinno być dostępne w inny sposób, jakimś specjalnym interfejsem, dostępnym tylko wewnątrz implementacji. Użytkownik powinien dostać do tego standardowe API, z operatorem porównania porównującym wartości. Zauważ, po co w C++ stosuje się wskaźniki i referencje do takich typów jak int, czy std::string. Jeśli już, to stosuje się albo uogólnienie przekazywania (const T&), albo przekazuje się do zmodyfikowania (T&, T*). Czy widziałeś kiedykolwiek w jakimś rzeczywistym programie, żeby ktoś porównywał dwa wskaźniki do int (pomijając przypadek, gdy wskaźnik do int jest używany jako iterator do tablicy int-ów - czyli zastosowanie jest inne, niż wartość referencji)? Dlatego tożsamością dla obiektów wartościowych jest wartość. Obiekty mogą sobie tą wartość przekazywać jak chcą, a nawet - jak pamiętasz, dyskutowaliśmy o tym - wartości mogą być symulowane przez predefiniowane unikalne obiekty i w takim przypadku porównanie tożsamości takich obiektów jest równoważne porównaniu wartości, choć to już jest szczegół implementacyjny. -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Sun, 04 Mar 2007 21:21
Date: Sun, 04 Mar 2007 21:21
87 lines
4678 bytes
4678 bytes
Dnia Sun, 4 Mar 2007 17:30:21 +0100, Adam Karpierz skrobie: > "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?ć. > Czyli chodzi ci ogolnie o to, aby cos bylo sp...dzielone Nie. Chodzi o to, żeby nie było zjebane. > 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 Ok, o gustach możesz sobie podyskutować, jeśli lubisz, ja oczywiście będę mógł o tym również porozmawiać, jeśli masz na ten temat do powiedzenia cokolwiek więcej, niż "syf, a nie język". Aha, plus wszelkie "ile to ja mam lat doświadczenia". Przypomnę na marginesie, że tak mają to właśnie zrobione wszystkie języki "mainstreamowe". Aha, Perl również, chociaż wolałbym się nim raczej podcierać, niż podpierać. > Podobnie z operatorem przypisania Nie pisałem nic o operatorze przypisania. > Jelsi do skopowiania obiektu uzywa sie tego samego > operatora co do przypisania referencji to jest to rowniez syf. Problem polega na tym, że operator przypisania powinien być dostępny i tak tylko dla typów wartościowych. Przy czym typem wartościowym jest również referencja (wskaźnik w przypadku C++). > 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 No, dobrze, w ostateczności się zgodzę, że tak to ma być. Pod jednym wszakże warunkiem. Że dla każdego typu jest dostępny wyłącznie albo jeden albo drugi. W sumie na jedno wychodzi - reszta to kwestia składni. > Podobnie chodzi o to aby byl dostepny inny operator do > 'clone' obiektu a inny do zmiany referencji Może i tak być - włącznie z powyższym zastrzeżeniem. Fakt, to nie jest dobre, żeby stosować operator przypisania do typów niewartościowych. Powinno się stosować inne metody, tak dla rozróżnienia. > Porzadne jezyki tak maja (mialy nawet w latach 60-tych), Te tzw. "porządne języki" udostępniały wszystko dla wszystkich, przy czym sam musiałeś pamiętać, co jest czym dla ciebie. Dziękuję bardzo. Gdybym nie potrzebował odpowiedniego wspomagania decyzji i uwagi, to pisałbym w asemblerze. > a jesli np ten syf zwany C++ tego nie ma C++ akurat ma (Tcl też). > to nazwij to zwyczajnie syfem. Tak, i Javę, i C#, i Perla. Z największą przyjemnością ;) > i przejdz nad tym do porzadku dziennego, a nie probuj robic > z tego syfu kamieni szlachetnych. Nie jestem chemikiem i nie znam się na kamieniach szlachetnych. -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 05 Mar 2007 06:07
Date: Mon, 05 Mar 2007 06:07
209 lines
10205 bytes
10205 bytes
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ę?
>
> 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?
> 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++.
>
>> 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.
Że jak? Piersza linijka większości porządnych operatorów == ! Po co
porównywać zawartość tego samego obiektu?
> 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.
> 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ę
Od roku programuję w Javie, jakoś nieszczególnie mi to przeszkadza.
>> > 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.
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ć.
> 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.
Mimo to nie odważyłbym się na takie wyraźne i jednoznaczne nazwanie
pierwszych obiektów wartościowymi a drugich niewartościowymi.
>
> 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.
> 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. Dziwię się Twoją opinią, bo
sprawiasz wrażenie człowieka, który ma doświadczenie zawodowe i trochę
linii kodu wyprodukował.
>
>> > 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... :-)
--
Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 05 Mar 2007 06:07
Date: Mon, 05 Mar 2007 06:07
73 lines
4890 bytes
4890 bytes
Sektor van Skijlen wrote: > Dnia Sun, 04 Mar 2007 17:46:12 +0100, Marcin 'Qrczak' Kowalczyk skrobie: >> Dnia 04-03-2007, nie o godzinie 14:50 +0000, Sektor van Skijlen >> napisał(a): > >> > > 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ść. > >> To się sprawdza, ale tylko w językach, w których podstawowe wartości są >> realizowane przez obiekty immutable. Jeśli tak nie jest, czyli kiedy >> typ, który powinien być typem wartościowym, jest realizowany jako obiekt >> ze stanem, czyli kiedy ten obiekt ze stanem tak naprawdę modeluje >> zmienną tego typu, a nie wartość tego typu, to mamy konflikt: równość >> zmiennych powinna porównywać zmienne jako takie, ale częściej chcemy >> porównywać bieżące wartości tych zmiennych i to zazwyczaj robi operator >> ==. Czyli po pierwsze działa niezgodnie z ogólnymi wytycznymi, a po >> drugie porównanie zmiennych w razie czego też powinno być dostępne. > > Ha! W razie czego! > > No właśnie o to chodzi, że nie. Jeśli określamy dany typ jako wartościowy, > to tożsamość przechowującego ją obiektu nie powinna nas interesować w > ogóle. A zatem powszechnie stosowany "trik" polegający na sprawdzeniu tożsamości obiektu w pierszej linijce operatora == uważasz za błędny? Podobnie w operatorze =, w którym zapobiega to przypisania obiektu samemu sobie? > Jeśli jest to potrzebne do jakichś wewnętrznych operacji, to powinno być > dostępne w inny sposób, jakimś specjalnym interfejsem, dostępnym tylko > wewnątrz implementacji. Użytkownik powinien dostać do tego standardowe > API, z operatorem porównania porównującym wartości. > > Zauważ, po co w C++ stosuje się wskaźniki i referencje do takich typów jak > int, czy std::string. Jeśli już, to stosuje się albo uogólnienie > przekazywania (const T&), albo przekazuje się do zmodyfikowania (T&, T*). > Czy widziałeś kiedykolwiek w jakimś rzeczywistym programie, żeby ktoś > porównywał dwa wskaźniki do int (pomijając przypadek, gdy wskaźnik do int > jest używany jako iterator do tablicy int-ów - czyli zastosowanie jest > inne, niż wartość referencji)? Tak, w dowolnej konkretyzacji szablonu int'em. Nie każdemu chce się robić specjalne implementacje dla typów prostych. > Dlatego tożsamością dla obiektów wartościowych jest wartość. Obiekty mogą > sobie tą wartość przekazywać jak chcą, a nawet - jak pamiętasz, > dyskutowaliśmy o tym - wartości mogą być symulowane przez predefiniowane > unikalne obiekty i w takim przypadku porównanie tożsamości takich obiektów > jest równoważne porównaniu wartości, choć to już jest szczegół > implementacyjny. Nie zgadzam się. Każdy obiekt jest uproszczeniem rzeczywistości, a co za tym idzie z dużym prawdopodobieństwem mogą pojawić się obiekty o tych samych wartościach, które nie są tymi samymi obiektami. To, że mam kolor oczu jak Brad Pitt nie czyni mnie Bradem Pitem o czym zaświadczy każdy stosowny operator porównania - tu: kobieta ;-) A poważnie: trzymajmy się terminologii, która była, jest i sprawdza się: obiekt (zestaw wartości) i identyfikator obiektu (tożsamość). Nie twórzmy nowych teorii na temat abstrakcji, która już została odpowiednio steoretyzowna. -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 05 Mar 2007 06:09
Date: Mon, 05 Mar 2007 06:09
17 lines
1753 bytes
1753 bytes
Adam Karpierz wrote: > "Mariusz Lotko" <imie.nazwisko@wp.pl> wrote: >> Adam Karpierz wrote: > >>>> 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ść. > > Prosze mi nie przypisywac slow Sekatora :) Przepraszam, myślałem, że głębokość cytowania jest już wystarczającym rozróżnikiem :-) -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Mon, 05 Mar 2007 21:38
Date: Mon, 05 Mar 2007 21:38
86 lines
5285 bytes
5285 bytes
Dnia Mon, 05 Mar 2007 07:07:55 +0100, Mariusz Lotko skrobie:
> > No właśnie o to chodzi, że nie. Jeśli określamy dany typ jako wartościowy,
> > to tożsamość przechowującego ją obiektu nie powinna nas interesować w
> > ogóle.
> A zatem powszechnie stosowany "trik" polegający na sprawdzeniu tożsamości
> obiektu w pierszej linijce operatora == uważasz za błędny?
Tak.
> Podobnie w operatorze =, w którym zapobiega to przypisania obiektu
> samemu sobie?
Tu już nie, ale to jest związane z tzw. kwestią językową. W przypadku C++ jest
to konieczne, jeżeli obiekt podawany jako argument operatora = jest
przekazywany przez referencję.
Nie byłoby natomiast tego problemu w przypadku, gdyby ten obiekt był tam
przekazywany przez wartość.
Gdyby hipotetycznie w Javie była możliwość zrobienia czegoś podobnego, to tam
też nie ma konieczności dodawania takiego sprawdzenia:
class K
{
private String s;
public void copyFrom( K x )
{
s = x.s;
}
...
}
Wywołanie K.copyFrom( this ) nie spowoduje błędu w tym przypadku.
> > Zauważ, po co w C++ stosuje się wskaźniki i referencje do takich typów jak
> > int, czy std::string. Jeśli już, to stosuje się albo uogólnienie
> > przekazywania (const T&), albo przekazuje się do zmodyfikowania (T&, T*).
> > Czy widziałeś kiedykolwiek w jakimś rzeczywistym programie, żeby ktoś
> > porównywał dwa wskaźniki do int (pomijając przypadek, gdy wskaźnik do int
> > jest używany jako iterator do tablicy int-ów - czyli zastosowanie jest
> > inne, niż wartość referencji)?
> Tak, w dowolnej konkretyzacji szablonu int'em. Nie każdemu chce się
> robić specjalne implementacje dla typów prostych.
Przy uogólnianiu oczywiście jest to prawda, z tą tylko różnicą, że tam typ
parametryczny T traktuje się prawdopodobnie zawsze jak typ obiektowy, więc
sprawa konkretyzacji na int nie ma i tak znaczenia.
Ale jeśli jest traktowany jako typ obiektowy, a nie wartościowy, to również
istnieje przekazywanie przez referencję, czy nieużywanie operatora == (bo nie
wiadomo, czy zdefiniowany) itd. - czyli typu T nie uważa się za wartościowy.
> > Dlatego tożsamością dla obiektów wartościowych jest wartość. Obiekty mogą
> > sobie tą wartość przekazywać jak chcą, a nawet - jak pamiętasz,
> > dyskutowaliśmy o tym - wartości mogą być symulowane przez predefiniowane
> > unikalne obiekty i w takim przypadku porównanie tożsamości takich obiektów
> > jest równoważne porównaniu wartości, choć to już jest szczegół
> > implementacyjny.
> Nie zgadzam się. Każdy obiekt jest uproszczeniem rzeczywistości, a co za tym
> idzie z dużym prawdopodobieństwem mogą pojawić się obiekty o tych samych
> wartościach, które nie są tymi samymi obiektami.
Jeśli mówimy już o rzeczywistości - podaj mi przykład obiektu z
rzeczywistości, który posiada jednocześnie wartość i tożsamość.
> To, że mam kolor oczu jak Brad Pitt nie czyni mnie Bradem
> Pitem o czym zaświadczy każdy stosowny operator porównania - tu: kobieta ;-)
Ale kolor oczu nie stanowi o wartości człowieka, o czym również może
zaświadczyć wspomniany operator porównania ;)
> A poważnie: trzymajmy się terminologii, która była, jest i sprawdza się:
> obiekt (zestaw wartości) i identyfikator obiektu (tożsamość). Nie twórzmy
> nowych teorii na temat abstrakcji, która już została odpowiednio
> steoretyzowna.
Ja nie tworzę żadnych nowych teorii - ja tylko obserwuję rzeczywistość.
--
// _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Mariusz Lotko
Date: Mon, 05 Mar 2007 22:58
Date: Mon, 05 Mar 2007 22:58
86 lines
5212 bytes
5212 bytes
Sektor van Skijlen wrote: > Dnia Mon, 05 Mar 2007 07:07:55 +0100, Mariusz Lotko skrobie: >> > No właśnie o to chodzi, że nie. Jeśli określamy dany typ jako >> > wartościowy, to tożsamość przechowującego ją obiektu nie powinna nas >> > interesować w ogóle. > >> A zatem powszechnie stosowany "trik" polegający na sprawdzeniu tożsamości >> obiektu w pierszej linijce operatora == uważasz za błędny? > > Tak. Wybacz, ale powyższym stwierdzeniem skłaniasz mnie do stwierdzenia u Ciebie paranoi... Przecież stosowanie tego jest oczywiste. Po co mam sprawdzać, czy mam tyle samo pieniędzy w swoim portfelu co... w swoim? > >> Podobnie w operatorze =, w którym zapobiega to przypisania obiektu >> samemu sobie? > > Tu już nie, ale to jest związane z tzw. kwestią językową. W przypadku C++ > jest to konieczne, jeżeli obiekt podawany jako argument operatora = jest > przekazywany przez referencję. > > Nie byłoby natomiast tego problemu w przypadku, gdyby ten obiekt był tam > przekazywany przez wartość. > > Gdyby hipotetycznie w Javie była możliwość zrobienia czegoś podobnego, to > tam też nie ma konieczności dodawania takiego sprawdzenia: Z tym, że w obu przypadkach nie chodzi o "przykrą konieczność", a o "wspaniałą możliwość" szybkiego stwierdzenia, że chodzi o "te same" a więc na pewno "takie same" obiekty. >> > Zauważ, po co w C++ stosuje się wskaźniki i referencje do takich typów >> > jak int, czy std::string. Jeśli już, to stosuje się albo uogólnienie >> > przekazywania (const T&), albo przekazuje się do zmodyfikowania (T&, >> > T*). Czy widziałeś kiedykolwiek w jakimś rzeczywistym programie, żeby >> > ktoś porównywał dwa wskaźniki do int (pomijając przypadek, gdy wskaźnik >> > do int jest używany jako iterator do tablicy int-ów - czyli >> > zastosowanie jest inne, niż wartość referencji)? > >> Tak, w dowolnej konkretyzacji szablonu int'em. Nie każdemu chce się >> robić specjalne implementacje dla typów prostych. > > Przy uogólnianiu oczywiście jest to prawda, z tą tylko różnicą, że tam typ > parametryczny T traktuje się prawdopodobnie zawsze jak typ obiektowy, więc > sprawa konkretyzacji na int nie ma i tak znaczenia. "Prawdopodobnie" to dla mnie trochę za mało. Szczególnie w przypadku szablonów, które według mojej praktyki z reguły są po prostu przeznaczone dla obiektów oferujących określony interfejs. I innych ograniczeń w ich użyciu właściwie nie ma. > Ale jeśli jest traktowany jako typ obiektowy, a nie wartościowy, to > również istnieje przekazywanie przez referencję, czy nieużywanie operatora > == (bo nie wiadomo, czy zdefiniowany) itd. - czyli typu T nie uważa się za > wartościowy. Takich założeń raczej też się nie podejmuje w C++. Jeśli coś nie jest zdefiniowane, to poinformuje nas o tym kompilator w czasie konkretyzacji szablonu. >> > Dlatego tożsamością dla obiektów wartościowych jest wartość. Obiekty >> > mogą sobie tą wartość przekazywać jak chcą, a nawet - jak pamiętasz, >> > dyskutowaliśmy o tym - wartości mogą być symulowane przez >> > predefiniowane unikalne obiekty i w takim przypadku porównanie >> > tożsamości takich obiektów jest równoważne porównaniu wartości, choć to >> > już jest szczegół implementacyjny. > >> Nie zgadzam się. Każdy obiekt jest uproszczeniem rzeczywistości, a co za >> tym idzie z dużym prawdopodobieństwem mogą pojawić się obiekty o tych >> samych wartościach, które nie są tymi samymi obiektami. > > Jeśli mówimy już o rzeczywistości - podaj mi przykład obiektu z > rzeczywistości, który posiada jednocześnie wartość i tożsamość. Konto bankowe. Tożsamość: numer, wartość: saldo. Nie chciałbym mieć konta w banku, który ma kłopot z odróżnieniem wartości mojego konta od jego tożsamości. -- Mariusz Lotko
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: 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
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Marcin 'Qrczak' Kowalczyk
Date: Mon, 05 Mar 2007 23:36
Date: Mon, 05 Mar 2007 23:36
53 lines
4235 bytes
4235 bytes
Dnia 04-03-2007, nie o godzinie 22:09 +0000, Sektor van Skijlen
napisał(a):
> 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.
Ten idealistyczny obraz, teoretycznie słuszny, sprawia pewne trudności
w językach, w których wiele podstawowych typów jest zmienialnych.
(Wyjątkowo nie dotyczy to C++, które pracuje w innym paradygmacie:
powszechnie niejawnie kopiuje obiekty, przez co zmienialność obiektów
ma węższe konsekwencje. Przy innym stylu programowania analogie między
językami przestają działać.)
Trudności polegają na tym, że jeśli np. jedyny typ stringów jest
zmienialny, to formalnie przestaje być typem wartościowym. Sam
napisałeś: „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ą”. Tyle że w takim języku on jest
również powszechnie używany w roli typu wartościowego! Prawdopodobnie
częściej niż jako „zmienna stringowa”. Większość użyć wykorzystuje
zmienialność najwyżej w trakcie konstrukcji, a później taki obiekt już
nie jest zmieniany — za to różne moduły swobodnie przechowują wskaźniki
do niego, zakładając, że już się nie zmieni. Porównanie jego zawartości
staje się powszechne.
Stąd część języków wychodzi z założenia, że będzie to bardziej
praktycznie, jeśli domyślna równość w takim przypadku porówna zawartość.
Czyli dla takich obiektów mamy dwa sensowne warianty równości.
Zwłaszcza że tożsamość różnych prostych typów, np. kolekcji, częściej
istnieje na poziomie koncepcyjnym (klonujemy obiekt, kiedy mamy ochotę
zapamiętać jego bieżący stan, ale jeszcze go zmieniać, i pilnujemy się,
w które miejsce przekazujemy którego klona) niż w sensie jawnego
porównania tożsamości dwóch obiektów nieznanego pochodzenia.
Tak jest na przykład w Pythonie w przypadku list i słowników (ale nie
stringów, które są immutable).
Lisp i Scheme są zgodne z ogólną teorią, jeśli za podstawową równość
(czy też równoważność) przyjąć EQL / eqv?; ona nie zmienia się w czasie
i zmienialne obiekty porównuje po tożsamości, a liczby i znaki po
wartości (niestety nie można robić własnych typów wartościowych).
Ale ponieważ stringi, listy i tablice są dostępne wyłącznie w wersji
zmienialnej, mamy też EQUAL / equal?, które schodzi do ich elementów,
w dodatku rekurencyjnie z tą samą operacją.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Wed, 07 Mar 2007 17:00
Date: Wed, 07 Mar 2007 17:00
214 lines
11074 bytes
11074 bytes
Dnia Tue, 06 Mar 2007 00:15:37 +0100, Mariusz Lotko skrobie:
> >> 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.
Tożsamości obiektów wskazywanych przez te wskaźniki. To nie zmienia faktu, że
wskaźniki są wartościami i ich porównanie jest porównaniem wartości.
> Czy tożsamość przeradza się w wartość jeśli
> obiekt jest inteligentny (smart)? ;-)
Nic takiego nie napisałem. Przecież te wartości to również wskaźniki.
Nie pomerdały ci się czasem obiekty wskazujące i obiekty wskazywane?
> >> > 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?
W żadnym z tych przypadków.
> >> Ż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ę.
Teoretycznie można - ale w założeniu obiekty wartościowe są obiektami małymi,
bo w obiektach dużych nie opłaca się tak określać wartości.
Obiekty wartościowe powinny być szczególnie przeznaczone do tego, żeby
identyfikować się przez wartość, a co za tym idzie, tanio się porównywać i
tanio kopiować.
Nie ma ściśle określone, co to znaczy, że obiekt jest duży, ale jeśli
porównanie tożsamości obiektów porównywanych przed porównaniem ich wartości
jest opłacalne, to znaczy, że obiekt jest "za duży" jak na obiekt wartościowy.
> > 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?
Moja teoria ma odniesienie do projektowania, a nie do języka.
Nie zabrania ona używania wskaźników do obiektów wartościowych, ale pod
warunkiem, że ich używanie jest sprawą czysto językową (typu przekazanie przez
wskaźnik/referencję, czy konieczność weryfikacji w operatorze przypisania),
nie może natomiast służyć do wydawania decyzji na podstawie określania
tożsamości obiektu. To ostatnie może być brane pod uwagę tylko przez metody
danej klasy z uwagi na konieczność posiadania dostępu do różnych detali
implementacyjnych. Zewnętrze tego nie powinno potrzebować.
> >> > 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ć.
To lepiej sobie przypomnij - bo sytuacji, żeby ktokolwiek w jakimś programie
sprawdzał, czy "a.x == b.x, ale ile wynosi a.x nie mam zielonego pojęcia", ja
sobie nie przypominam.
> >> > 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.
A co mają do tego 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ę.
Bo modyfikacja w obiekcie typu StringBuilder jest widziana w każdym miejscu,
gdzie jest trzymana referencja do tego obiektu.
W przypadku typu String z przyczyn oczywistych ta zależność nie zachodzi.
> >> > 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.
Czyli właśnie strzeliłeś sobie gola ;)
Jak najbardziej chcemy sprawdzić, czy dziewczyna.stan == "wolny".
Ale nie ma sensu sprawdzanie, czy dziewczyna.stan == me.stan, jeśli nie wiemy
jaki jest stan jednego z tych obiektów.
> >> 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?
To jest zupełnie inna sprawa - to nie jest porównywanie, tylko porządkowanie
(zgodnie z terminologią STL - operator <).
--
// _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Wed, 07 Mar 2007 17:44
Date: Wed, 07 Mar 2007 17:44
99 lines
6751 bytes
6751 bytes
Dnia Tue, 06 Mar 2007 00:36:01 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 04-03-2007, nie o godzinie 22:09 +0000, Sektor van Skijlen > napisał(a): > > 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. > Ten idealistyczny obraz, teoretycznie słuszny, sprawia pewne trudności > w językach, w których wiele podstawowych typów jest zmienialnych. > (Wyjątkowo nie dotyczy to C++, które pracuje w innym paradygmacie: > powszechnie niejawnie kopiuje obiekty, przez co zmienialność obiektów > ma węższe konsekwencje. Przy innym stylu programowania analogie między > językami przestają działać.) Zgadza się - ale nie tylko dlatego. Obiekty niewartościowe jak najbardziej występują w C++. Chodzi tylko o to, że w C++ - w odróżnieniu od większości języków - można tworzyć własne typy wartościowe. Fakt, że każdy typ ma domyślne traktowanie jako wartościowy, jest przykrą konsekwencją drobnego uogólnienia (jego brak zwykle oznacza, że nie da się tworzyć własnych typów wartościowych; w C# zrobili dobrą przymiarkę na udostępnienie tego inną metodą, tylko niestety sprawę spartolili). > Trudności polegają na tym, że jeśli np. jedyny typ stringów jest > zmienialny, to formalnie przestaje być typem wartościowym. Sam > napisałeś: ?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ą?. Tyle że w takim języku on jest > również powszechnie używany w roli typu wartościowego! Ha! Wynika to z faktu, że string z natury jest typem wartościowym. Jeśli język nie umożliwia zrobienia takiego typu wartościowego, to trzeba robić obejścia w postaci obiektu niemodyfikowalnego. > Prawdopodobnie > częściej niż jako ?zmienna stringowa?. Większość użyć wykorzystuje > zmienialność najwyżej w trakcie konstrukcji, a później taki obiekt już > nie jest zmieniany ? za to różne moduły swobodnie przechowują wskaźniki > do niego, zakładając, że już się nie zmieni. Porównanie jego zawartości > staje się powszechne. Zgadza się - ale skoro jest to obiekt niemodyfikowalny, to może być traktowany jako typ wartościowy, gdyż zmienność w tym przypadku nie powoduje konsekwencji wchodzenia zmienności w interakcję z tożsamością. De facto zatem, tożsamość takich obiektów nie ma dla nas znaczenia, co wystarcza do stwierdzenia, że jest to typ wartościowy. Ale skoro tak, to i porównywanie tego obiektu powinno porównywać wartość, a nie tożsamość. I tak właśnie jest w C#. > Stąd część języków wychodzi z założenia, że będzie to bardziej > praktycznie, jeśli domyślna równość w takim przypadku porówna zawartość. > Czyli dla takich obiektów mamy dwa sensowne warianty równości. Ale tylko jeden z tych wariantów ma sens. Tożsamość dwóch obiektów typu string, jeśli to są obiekty niezmienialne, jest nieistotna - program nie powinien w żadnym przypadku polegać na tej tożsamości. Tożsamość jest ważna, jeśli obiekt jest zmienialny. > Zwłaszcza że tożsamość różnych prostych typów, np. kolekcji, częściej > istnieje na poziomie koncepcyjnym (klonujemy obiekt, kiedy mamy ochotę > zapamiętać jego bieżący stan, ale jeszcze go zmieniać, i pilnujemy się, > w które miejsce przekazujemy którego klona) niż w sensie jawnego > porównania tożsamości dwóch obiektów nieznanego pochodzenia. > Tak jest na przykład w Pythonie w przypadku list i słowników (ale nie > stringów, które są immutable). Nie rozumiem. > Lisp i Scheme są zgodne z ogólną teorią, jeśli za podstawową równość > (czy też równoważność) przyjąć EQL / eqv?; ona nie zmienia się w czasie > i zmienialne obiekty porównuje po tożsamości, a liczby i znaki po > wartości (niestety nie można robić własnych typów wartościowych). > Ale ponieważ stringi, listy i tablice są dostępne wyłącznie w wersji > zmienialnej, mamy też EQUAL / equal?, które schodzi do ich elementów, > w dodatku rekurencyjnie z tą samą operacją. O ile sobie przypominasz, w którejś z naszych wcześniejszych dyskusji nawet zgodziliśmy się co do tego. Różnica polega jedynie na tym, czy można tworzyć własne typy wartościowe i czy można obiekty wartościowe modyfikować w miejscu. Ale te sprawy są już ściśle związane z określonymi ficzerami językowymi. Jeśli język umożliwiałby tylko chociażby możliwość definiowania własnych typów wartościowych, to rozróżnianie porównania tożsamości i porównania wartości nie byłoby potrzebne. Śmiem wręcz twierdzić, że wystarczyłaby do tego konstrukcja językowa, która tak stanowi i jednocześnie uniemożliwia modyfikację takiego obiektu. -- // _ ___ 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"
Re: pl.comp.objects FAQ (Frequently Asked Questions and more)
Author: Sektor van Skijlen
Date: Wed, 07 Mar 2007 17:52
Date: Wed, 07 Mar 2007 17:52
119 lines
6983 bytes
6983 bytes
Dnia Mon, 05 Mar 2007 23:58:08 +0100, Mariusz Lotko skrobie: > Sektor van Skijlen wrote: > > Dnia Mon, 05 Mar 2007 07:07:55 +0100, Mariusz Lotko skrobie: > >> > No właśnie o to chodzi, że nie. Jeśli określamy dany typ jako > >> > wartościowy, to tożsamość przechowującego ją obiektu nie powinna nas > >> > interesować w ogóle. > > > >> A zatem powszechnie stosowany "trik" polegający na sprawdzeniu tożsamości > >> obiektu w pierszej linijce operatora == uważasz za błędny? > > > > Tak. > Wybacz, ale powyższym stwierdzeniem skłaniasz mnie do stwierdzenia u Ciebie > paranoi... Przecież stosowanie tego jest oczywiste. Po co mam sprawdzać, > czy mam tyle samo pieniędzy w swoim portfelu co... w swoim? Portfel nie jest typem wartościowym. Ilość pieniędzy w portfelu jest jedynie jednym ze stanów tego obiektu, podobnie jak ilość kart kredytowych w środku, kolor portfela i materiał, z którego go wykonano. Typem wartościowym może być kolor. Porównanie dwóch obiektów typu kolor można porównać ze sprawdzeniem, czy na dwóch kartkach papieru zapisany tam kod koloru jest ten sam. Ty chcesz, żeby przed odczytaniem numeru z każdej kartki najpierw sprawdzić, czy te obie kartki to czasem nie jest jedna i ta sama kartka. Jaki to ma sens? > >> Podobnie w operatorze =, w którym zapobiega to przypisania obiektu > >> samemu sobie? > > > > Tu już nie, ale to jest związane z tzw. kwestią językową. W przypadku C++ > > jest to konieczne, jeżeli obiekt podawany jako argument operatora = jest > > przekazywany przez referencję. > > > > Nie byłoby natomiast tego problemu w przypadku, gdyby ten obiekt był tam > > przekazywany przez wartość. > > > > Gdyby hipotetycznie w Javie była możliwość zrobienia czegoś podobnego, to > > tam też nie ma konieczności dodawania takiego sprawdzenia: > Z tym, że w obu przypadkach nie chodzi o "przykrą konieczność", a > o "wspaniałą możliwość" szybkiego stwierdzenia, że chodzi o "te same" > a więc na pewno "takie same" obiekty. To jest przykra konieczność. Musisz to po prostu zrobić, bo inaczej będzie wylot. Ta "wspaniała możliwość" z kolei powoduje droższe porównanie. > >> > Zauważ, po co w C++ stosuje się wskaźniki i referencje do takich typów > >> > jak int, czy std::string. Jeśli już, to stosuje się albo uogólnienie > >> > przekazywania (const T&), albo przekazuje się do zmodyfikowania (T&, > >> > T*). Czy widziałeś kiedykolwiek w jakimś rzeczywistym programie, żeby > >> > ktoś porównywał dwa wskaźniki do int (pomijając przypadek, gdy wskaźnik > >> > do int jest używany jako iterator do tablicy int-ów - czyli > >> > zastosowanie jest inne, niż wartość referencji)? > > > >> Tak, w dowolnej konkretyzacji szablonu int'em. Nie każdemu chce się > >> robić specjalne implementacje dla typów prostych. > > > > Przy uogólnianiu oczywiście jest to prawda, z tą tylko różnicą, że tam typ > > parametryczny T traktuje się prawdopodobnie zawsze jak typ obiektowy, więc > > sprawa konkretyzacji na int nie ma i tak znaczenia. > "Prawdopodobnie" to dla mnie trochę za mało. Szczególnie w przypadku > szablonów, które według mojej praktyki z reguły są po prostu przeznaczone > dla obiektów oferujących określony interfejs. I innych ograniczeń w ich > użyciu właściwie nie ma. Tak, dokładnie. Ale typy wartościowe zwykle mają inny interfejs, niż typy obiektowe. > > Ale jeśli jest traktowany jako typ obiektowy, a nie wartościowy, to > > również istnieje przekazywanie przez referencję, czy nieużywanie operatora > > == (bo nie wiadomo, czy zdefiniowany) itd. - czyli typu T nie uważa się za > > wartościowy. > Takich założeń raczej też się nie podejmuje w C++. Jeśli coś nie jest > zdefiniowane, to poinformuje nas o tym kompilator w czasie konkretyzacji > szablonu. Powodując, że dla danego typu nie da się tego szablonu zastosować, więc nie ma tematu. > >> > Dlatego tożsamością dla obiektów wartościowych jest wartość. Obiekty > >> > mogą sobie tą wartość przekazywać jak chcą, a nawet - jak pamiętasz, > >> > dyskutowaliśmy o tym - wartości mogą być symulowane przez > >> > predefiniowane unikalne obiekty i w takim przypadku porównanie > >> > tożsamości takich obiektów jest równoważne porównaniu wartości, choć to > >> > już jest szczegół implementacyjny. > > > >> Nie zgadzam się. Każdy obiekt jest uproszczeniem rzeczywistości, a co za > >> tym idzie z dużym prawdopodobieństwem mogą pojawić się obiekty o tych > >> samych wartościach, które nie są tymi samymi obiektami. > > > > Jeśli mówimy już o rzeczywistości - podaj mi przykład obiektu z > > rzeczywistości, który posiada jednocześnie wartość i tożsamość. > Konto bankowe. Tożsamość: numer, wartość: saldo. Oraz wartość: właściciel (można go potem kiedyś zmienić) Oraz obiekt: historia transakcji Oraz... Czy ty w ogóle wiesz, co to jest "wartość"? > Nie chciałbym mieć konta w banku, który ma kłopot z odróżnieniem > wartości mojego konta od jego tożsamości. Na razie to masz problem z odróżnieniem wartości od stanu. -- // _ ___ 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"
Wartości i obiekty
Author: Marcin 'Qrczak' Kowalczyk
Date: Wed, 07 Mar 2007 23:32
Date: Wed, 07 Mar 2007 23:32
112 lines
7604 bytes
7604 bytes
Dnia 07-03-2007, śro o godzinie 17:44 +0000, Sektor van Skijlen
napisał(a):
> > Trudności polegają na tym, że jeśli np. jedyny typ stringów jest
> > zmienialny, to formalnie przestaje być typem wartościowym. Sam
> > napisałeś: ?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ą?. Tyle że w takim języku on jest
> > również powszechnie używany w roli typu wartościowego!
>
> Ha! Wynika to z faktu, że string z natury jest typem wartościowym. Jeśli
> język nie umożliwia zrobienia takiego typu wartościowego, to trzeba robić
> obejścia w postaci obiektu niemodyfikowalnego.
To nie jest obejście. W językach, w których obiekt jest podstawowym
pojęciem pierwotnym, kwintesencją typu wartościowego jest obiekt
niemodyfikowalny.
(Można też wyjść od wartości jako pojęcia pierwotnego, a obiekty budować
z pogrupowanych w rekordy i inne struktury zmiennych zawierających
wartości. Takie podejście wydaje się właściwym sposobem opisu SML-a
i Erlanga, gdzie współdzielenie fragmentów wartości jest nieobserwowalne
z poziomu języka źródłowego, mimo że implementacyjnie może ono wystąpić
bądź nie. Ale w większości języków wygodniej jest zacząć od obiektów.)
Jeśli odstawić na bok nietypowy punkt widzenia C++, to wartości dzielą
się na te, które są reprezentowane przez niezmienialne obiekty
o nieistotnej tożsamości, i na te, które są wskaźnikami na zmienialne
obiekty. Jest jeszcze trzecia kategoria leżąca pomiędzy tymi dwiema:
wskaźniki na singletony, czyli na jedyne obiekty danego rodzaju,
np. true / false / nil. Te obiekty są niezmienialne, ale tożsamość
tych obiektów jest dobrze zdefiniowana; rozróżnianie ich po tożsamości
jest równoważne rozróżnianiu po cechach wewnętrznych.
Wartości można umieszczać w zmiennych. Dana zmienna może zawierać różne
wartości w różnym czasie.
Jeśli spróbować dopasować do tego modelu C++, to się okaże, że zmienną
C++ zawierającą obiekt można rozumieć na dwa sposoby:
a) Jako zmienialny obiekt, przywiązany na stałe do swojej nazwy.
To tłumaczenie jest odpowiednie w przypadku obiektów z tożsamością,
zwłaszcza złożonych, bo pozwala wymodelować możliwość zmiany
indywidualnych pól obiektu z zachowaniem tożsamości całego obiektu.
Takie obiekty są zwykle przekazywane przez referencje C++ albo
wskaźniki C++, co odpowiada przekazaniu wskaźnika na obiekt
w modelu, a więc odpowiada naturalnemu sposobowi przekazania
wartości w modelu.
b) Jako zmienną zawierającą wartość, która sama jest niezmienialna.
To tłumaczenie jest lepsze dla atomowych typów wartościowych,
bo pozwala wymodelować wartość wyabstrahowaną od miejsca
przechowywania. Takie obiekty są w C++ zwykle kopiowane,
co odpowiada przekazaniu odczytanej bieżącej wartości zmiennej
w modelu, czyli znowu jest naturalnym sposobem przekazania wartości,
mimo że w C++ jest inne niż tamto.
Użycie do atomowych typów wartościowych mapowania a) zamiast b)
wymagałoby klonowania obiektów, co jest nienaturalne i niewygodne,
normalnie nie jest wspierane składniowo. Z drugiej strony, użycie do
złożonych obiektów mapowania b) zamiast a) wymagałoby wymodelowania
przekazania wskaźnika za pomocą wskaźnika na zmienną, co w wielu
językach nie jest nawet wspierane. Dlatego zdecydowanie się na jeden
sposób mapowania prowadziłoby do nienaturalnego kodu w modelu
w części przypadków.
Istnienie dwóch możliwych mapowań z nieoczywistym wyborem między nimi
powoduje, że realizacje zadań nie przekładają się między C++ a innymi
językami dosłownie ani konsekwentnie.
W C++ jest grupa typów, które mają złożoną strukturę wewnętrzną, ale
których kopiowanie ma sens, np. string albo vector. Takie obiekty czasem
są kopiowane, czyli przekazywane przez wartość, a czasem są przekazywane
referencje do nich. Tutaj wybór mapowania jest szczególnie nieoczywisty,
bo można traktować te obiekty albo jako wartości (i zrealizować je jako
obiekty niezmienialne, swobodnie przekazywane między zmiennymi, ale
tworzone na nowo przy obliczeniach), albo jako obiekty z tożsamością
(i zrealizować je jako obiekty zmienialne, jawnie klonowane w razie
potrzeby).
To wszystko dotyczyło obiektów zawartych w zmiennych. W C++ jeszcze są
obiekty alokowane na stercie i przekazywane przez wskaźniki. One mają
jednoznaczne przełożenie na ten model, które jest podobne do wersji a).
Przy tłumaczeniu w drugą stronę, na C++, ten wybór teoretycznie byłby
uniwersalny, tyle że C++ unika takich obiektów z powodu braku
odśmiecania, więc jest tendencja do umieszczenia obiektu od razu
w zmiennej.
> > Prawdopodobnie
> > częściej niż jako ?zmienna stringowa?. Większość użyć wykorzystuje
> > zmienialność najwyżej w trakcie konstrukcji, a później taki obiekt już
> > nie jest zmieniany ? za to różne moduły swobodnie przechowują wskaźniki
> > do niego, zakładając, że już się nie zmieni. Porównanie jego zawartości
> > staje się powszechne.
>
> Zgadza się - ale skoro jest to obiekt niemodyfikowalny, to może być traktowany
> jako typ wartościowy, gdyż zmienność w tym przypadku nie powoduje konsekwencji
> wchodzenia zmienności w interakcję z tożsamością.
Pisałem tutaj o zmienialnym stringu, zakładając, że to jest jedyny
string w danym języku. Czyli kiedy złożony typ pełniący rolę typu
wartościowego jest jednak zmienialny. Taka sytuacja jest kłopotliwa.
Mój model w wersji czystej wymaga zdecydowania się, który styl użycia
jest tutaj dominujący. Pomieszanie styli grozi błędami aliasowania albo
niepotrzebnymi kopiami. Jeśli w różnych miejscach programu ten sam typ
jest używany w różnym stylu, to trudno zrobić jeden operator porównania,
który pasuje do obu.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: Wartości i obiekty
Author: Sektor van Skijlen
Date: Sat, 10 Mar 2007 18:47
Date: Sat, 10 Mar 2007 18:47
192 lines
10593 bytes
10593 bytes
Dnia Thu, 08 Mar 2007 00:32:04 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > To nie jest obejście. W językach, w których obiekt jest podstawowym > pojęciem pierwotnym, kwintesencją typu wartościowego jest obiekt > niemodyfikowalny. No wtedy tak. Nie twierdzę, że tak jest dobrze, czy źle - to jest szczegół. Po prostu konsekwencją nieistnienia naturalnych typów wartościowych jest to, że typy wartościowe należy definiować jako stałe obiekty. > Jeśli odstawić na bok nietypowy punkt widzenia C++, to wartości dzielą > się na te, które są reprezentowane przez niezmienialne obiekty > o nieistotnej tożsamości, i na te, które są wskaźnikami na zmienialne > obiekty. O istniejącej tożsamości. :) > Jest jeszcze trzecia kategoria leżąca pomiędzy tymi dwiema: > wskaźniki na singletony, czyli na jedyne obiekty danego rodzaju, > np. true / false / nil. Te obiekty są niezmienialne, ale tożsamość > tych obiektów jest dobrze zdefiniowana; rozróżnianie ich po tożsamości > jest równoważne rozróżnianiu po cechach wewnętrznych. Nie tworzyłbym specjalnej kategorii dla tych obiektów. Po pierwsze, są one stałe, więc bez problemów można je zaliczyć do typów wartościowych. Po drugie, kwestia sposobu ich porównania może być kwestią czysto implementacyjną. O ile sobie przypominasz, wskazywałem ci już kiedyś, że jest możliwe takie zorganizowanie wartości całkowitych, że każdej liczbie odpowiada obiekt. Każda nowo powstała liczba będzie albo nowo utworzonym obiektem, a jeśli jest już obiekt, który symbolizuje daną liczbę, to się go znajduje i zwraca. W takim przypadku możemy śmiało stwierdzić, że każdy obiekt symbolizujący liczbę całkowitą jest unikalny - nie ma dwóch obiektów o takiej samej zawartości. Jest to oczywiście nieoptymalne i nikt tego jak najbardziej nie robi, ale jest to przykład na to, że liczby mogą być takimi właśnie "singletonami". Więc jeśli mamy pewność, że istnieje tylko jeden obiekt określonej klasy w całym systemie, który posiada określoną zawartość, to jest oczywiste, że porównanie tożsamości tych obiektów da ten sam wynik, co porównanie ich zawartości. Ale sposób porównywania tych obiektów, które są typami wartościowymi, powinien zależeć już od implementacji. Efekt jest taki, że nawet jeśli zrobimy ten podział wedle tego, co mówisz, to potrzebujemy następujących typów i odpowiadających im domyślnych metod porównania: 1. Obiektów modyfikowalnych, które są porównywane po tożsamości 2. Obiektów stałych, które są porównywane po zawartości 3. Obiektów stałych unikalnych, które są porównywane po tożsamości I do żadnego z rodzajów typów tych obiektów nie potrzebujemy nigdy dwóch osobnych operatorów porównania. > Wartości można umieszczać w zmiennych. Dana zmienna może zawierać różne > wartości w różnym czasie. Tak. > Jeśli spróbować dopasować do tego modelu C++, to się okaże, że zmienną > C++ zawierającą obiekt można rozumieć na dwa sposoby: > a) Jako zmienialny obiekt, przywiązany na stałe do swojej nazwy. > To tłumaczenie jest odpowiednie w przypadku obiektów z tożsamością, > zwłaszcza złożonych, bo pozwala wymodelować możliwość zmiany > indywidualnych pól obiektu z zachowaniem tożsamości całego obiektu. > Takie obiekty są zwykle przekazywane przez referencje C++ albo > wskaźniki C++, co odpowiada przekazaniu wskaźnika na obiekt > w modelu, a więc odpowiada naturalnemu sposobowi przekazania > wartości w modelu. > b) Jako zmienną zawierającą wartość, która sama jest niezmienialna. > To tłumaczenie jest lepsze dla atomowych typów wartościowych, > bo pozwala wymodelować wartość wyabstrahowaną od miejsca > przechowywania. Takie obiekty są w C++ zwykle kopiowane, > co odpowiada przekazaniu odczytanej bieżącej wartości zmiennej > w modelu, czyli znowu jest naturalnym sposobem przekazania wartości, > mimo że w C++ jest inne niż tamto. Szczerze mówiąc to nic z tego nie rozumiem. > Użycie do atomowych typów wartościowych mapowania a) zamiast b) > wymagałoby klonowania obiektów, co jest nienaturalne i niewygodne, > normalnie nie jest wspierane składniowo. Z drugiej strony, użycie do > złożonych obiektów mapowania b) zamiast a) wymagałoby wymodelowania > przekazania wskaźnika za pomocą wskaźnika na zmienną, co w wielu > językach nie jest nawet wspierane. Dlatego zdecydowanie się na jeden > sposób mapowania prowadziłoby do nienaturalnego kodu w modelu > w części przypadków. Jeszcze raz - tylko prościej ;) > Istnienie dwóch możliwych mapowań z nieoczywistym wyborem między nimi > powoduje, że realizacje zadań nie przekładają się między C++ a innymi > językami dosłownie ani konsekwentnie. Ale to nie ma większego znaczenia. > W C++ jest grupa typów, które mają złożoną strukturę wewnętrzną, ale > których kopiowanie ma sens, np. string albo vector. Vector moim zdaniem niespecjalnie. > Takie obiekty czasem > są kopiowane, czyli przekazywane przez wartość, a czasem są przekazywane > referencje do nich. Ale przekazywanie stringa przez referncję robi się wyłącznie ze względów optymalizacyjnych. Nie ma żadnych przesłanek czysto językowych, które by nakazywały inne przekazywanie, niż przez wartość. > Tutaj wybór mapowania jest szczególnie nieoczywisty, > bo można traktować te obiekty albo jako wartości (i zrealizować je jako > obiekty niezmienialne, swobodnie przekazywane między zmiennymi, ale > tworzone na nowo przy obliczeniach), albo jako obiekty z tożsamością > (i zrealizować je jako obiekty zmienialne, jawnie klonowane w razie > potrzeby). Tu się nie zgadzam. String zawsze powinien być traktowany jak wartość, natomiast wektor zawsze jak obiekt. > To wszystko dotyczyło obiektów zawartych w zmiennych. W C++ jeszcze są > obiekty alokowane na stercie i przekazywane przez wskaźniki. One mają > jednoznaczne przełożenie na ten model, które jest podobne do wersji a). > Przy tłumaczeniu w drugą stronę, na C++, ten wybór teoretycznie byłby > uniwersalny, tyle że C++ unika takich obiektów z powodu braku > odśmiecania, więc jest tendencja do umieszczenia obiektu od razu > w zmiennej. Przyczyny wydajnościowe również jednak istnieją :). Z tego przecież powodu podobno IBM-owska Java ma taki trik optymalizacyjny (którym miała podobno pognębić C#), że jeśli obiekt jest tworzony w funkcji i nigdzie nie przekazywany na zewnątrz tej funkcji (tzn. metody), to jest tworzony w całości na stosie. > > > Prawdopodobnie > > > częściej niż jako ?zmienna stringowa?. Większość użyć wykorzystuje > > > zmienialność najwyżej w trakcie konstrukcji, a później taki obiekt już > > > nie jest zmieniany ? za to różne moduły swobodnie przechowują wskaźniki > > > do niego, zakładając, że już się nie zmieni. Porównanie jego zawartości > > > staje się powszechne. > > > > Zgadza się - ale skoro jest to obiekt niemodyfikowalny, to może być traktowany > > jako typ wartościowy, gdyż zmienność w tym przypadku nie powoduje konsekwencji > > wchodzenia zmienności w interakcję z tożsamością. > Pisałem tutaj o zmienialnym stringu, zakładając, że to jest jedyny > string w danym języku. Czyli kiedy złożony typ pełniący rolę typu > wartościowego jest jednak zmienialny. Taka sytuacja jest kłopotliwa. Oj... nie bardzo to widzę. Takie coś jest możliwe w C++, który w naturalny sposób obsługuje typy wartościowe i pozwala typom definiować operatory. W ten sposób można zrobić typ wartościowy, którego obiekt jest modyfikowalny w miejscu. Jeśli język nie udostępnia takiego mechanizmu, to jest skazany na zrobienie takiego tricku, jak obiekt, którego nie można modyfikować po utworzeniu (bo nie ma operacji, które na to pozwalają). Język zatem powinien umożliwiać albo: - jak C++, zrobienie wszystkiego i przedefiniowanie wszystkich operatorów - pozwolić tylko na wybrane definicje - ale niech one umożliwią programiście zrobienie również typów wartościowyych > Mój model w wersji czystej wymaga zdecydowania się, który styl użycia > jest tutaj dominujący. Pomieszanie styli grozi błędami aliasowania albo > niepotrzebnymi kopiami. No właśnie - ale nie możesz zrobić tak, że w całym języku jeden model obowiązuje wszystkie obiekty. > Jeśli w różnych miejscach programu ten sam typ > jest używany w różnym stylu, to trudno zrobić jeden operator porównania, > który pasuje do obu. To wtedy trzeba zrobić osobne typy. Tak jak w Javie jest String i StringBuilder. -- // _ ___ 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"
Re: Wartości i obiekty
Author: Marcin 'Qrczak' Kowalczyk
Date: Sat, 10 Mar 2007 23:11
Date: Sat, 10 Mar 2007 23:11
117 lines
7040 bytes
7040 bytes
Dnia 10-03-2007, sob o godzinie 18:47 +0000, Sektor van Skijlen
napisał(a):
> > Jest jeszcze trzecia kategoria leżąca pomiędzy tymi dwiema:
> > wskaźniki na singletony, czyli na jedyne obiekty danego rodzaju,
> > np. true / false / nil. Te obiekty są niezmienialne, ale tożsamość
> > tych obiektów jest dobrze zdefiniowana; rozróżnianie ich po tożsamości
> > jest równoważne rozróżnianiu po cechach wewnętrznych.
>
> Nie tworzyłbym specjalnej kategorii dla tych obiektów.
Zwykle można je traktować razem z wartościowymi. Różnica objawia
się tylko wtedy, kiedy w języku mamy do dyspozycji operację jawnie
porównującą dwa obiekty po tożsamości. Tę operację można uznać za
niskopoziomową i rzadko się jej wprost używa, ale w wielu językach
jest dostępna, bo może być tańsza od domyślnego porównania, a dla
pewnego zbioru obiektów jest mu równoważna (Lisp: EQ, Scheme: eq?,
Python: is, Kogut: Is, OCaml: ==). Na przykład w Pythonie porównanie
"x is None" jest praktyczne, a "x is 5" nie jest.
> > Jeśli spróbować dopasować do tego modelu C++, to się okaże, że zmienną
> > C++ zawierającą obiekt można rozumieć na dwa sposoby:
>
> > a) Jako zmienialny obiekt, przywiązany na stałe do swojej nazwy.
> > To tłumaczenie jest odpowiednie w przypadku obiektów z tożsamością,
> > zwłaszcza złożonych, bo pozwala wymodelować możliwość zmiany
> > indywidualnych pól obiektu z zachowaniem tożsamości całego obiektu.
> > Takie obiekty są zwykle przekazywane przez referencje C++ albo
> > wskaźniki C++, co odpowiada przekazaniu wskaźnika na obiekt
> > w modelu, a więc odpowiada naturalnemu sposobowi przekazania
> > wartości w modelu.
>
> > b) Jako zmienną zawierającą wartość, która sama jest niezmienialna.
> > To tłumaczenie jest lepsze dla atomowych typów wartościowych,
> > bo pozwala wymodelować wartość wyabstrahowaną od miejsca
> > przechowywania. Takie obiekty są w C++ zwykle kopiowane,
> > co odpowiada przekazaniu odczytanej bieżącej wartości zmiennej
> > w modelu, czyli znowu jest naturalnym sposobem przekazania wartości,
> > mimo że w C++ jest inne niż tamto.
>
> Szczerze mówiąc to nic z tego nie rozumiem.
Bo opisałem odpowiedniki zmiennej w C++ językiem (ludzkim)
przystosowanym do opisywania innych języków (programowania).
Jesteś przyzwyczajony do języka (ludzkiego) przystosowanego
do opisywania C++.
Jeśli w C++ mamy zmienną zawierającą obiekt udostępniający jakieś metody
(w tym metody zmieniające jego stan), to w innym języku odpowiednik tej
konstrukcji wygląda z reguły na jeden z dwóch sposobów, zależnie od
stylu, w jakim przeważnie wygodnie jest używać obiektów danego typu:
a) Typowy przykład: tablica.
Zmienna wskazuje na obiekt udostępniający analogiczne operacje jak
w C++. Obiekt jest tworzony na stercie. Do tej zmiennej nie jest
nigdy przypisywany wskaźnik na inny obiekt.
Tam, gdzie w C++ obiekt jest przekazywany przez referencję, w innym
języku przekazywana jest wartość tej zmiennej (wskazująca na ten
obiekt). Tam, gdzie w C++ obiekt jest przekazywany przez wartość,
w innym języku obiekt jest klonowany (czymś w rodzaju metody Clone).
b) Typowy przykład: liczba.
Zmienna wskazuje na niezmienialny obiekt innego języka reprezentujący
bieżący stan obiektu C++. Metodom C++, które zmieniały stan obiektu,
odpowiadają operacje zwracające nowy obiekt, który jest przypisywany
z powrotem tej zmiennej.
Tam, gdzie w C++ obiekt jest przekazywany przez wartość, w innym
języku przekazywana jest bieżąca wartość zmiennej. Tam, gdzie
w C++ obiekt jest przekazywany przez referencję, w innym języku
przekazywana jest referencja na zmienną.
> String zawsze powinien być traktowany jak wartość, natomiast wektor zawsze
> jak obiekt.
Zgodzę się, że zazwyczaj. Nie zgadzam się, że zawsze.
A wektor znaków? Z jednej strony to jest wektor. Z drugiej strony to
jest w zasadzie to samo, co string. Różnice są w dodatkowych metodach,
ale one są raczej poboczne, nie wpływają na istotę rzeczy.
> > Pisałem tutaj o zmienialnym stringu, zakładając, że to jest jedyny
> > string w danym języku. Czyli kiedy złożony typ pełniący rolę typu
> > wartościowego jest jednak zmienialny. Taka sytuacja jest kłopotliwa.
>
> Oj... nie bardzo to widzę.
No i właśnie mówię, że to jest kłopotliwe. Lepiej tego unikać.
W to C++ pasuje. W Perlu też; to jest jeden z nielicznych języków
(obok Pascala, C i C++), który kopiuje zawartość stringa przy
przypisaniu, choć przy przekazaniu jako argument funkcji formalnie
już nie (ale w praktyce zwykle tak, bo większość funkcji zaczyna się
od skopiowania argumentów do osobnych lokalnych zmiennych - specyfika
Perla).
Przykłady języków, które mają wyłącznie zmienialne stringi mimo
paradygmatu, który do tego nie pasuje: Lisp, Scheme, OCaml, Ruby
(czasem są zmienialne łącznie ze zmianą długości, a czasem nie).
> > Mój model w wersji czystej wymaga zdecydowania się, który styl użycia
> > jest tutaj dominujący. Pomieszanie styli grozi błędami aliasowania albo
> > niepotrzebnymi kopiami.
>
> No właśnie - ale nie możesz zrobić tak, że w całym języku jeden model
> obowiązuje wszystkie obiekty.
Oczywiście, tego nie proponowałem. Byle był ustalony styl dla danego
typu.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: Wartości i obiekty
Author: Sektor van Skijlen
Date: Sun, 11 Mar 2007 15:29
Date: Sun, 11 Mar 2007 15:29
191 lines
10985 bytes
10985 bytes
Dnia Sun, 11 Mar 2007 00:11:42 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 10-03-2007, sob o godzinie 18:47 +0000, Sektor van Skijlen > napisał(a): > > > Jest jeszcze trzecia kategoria leżąca pomiędzy tymi dwiema: > > > wskaźniki na singletony, czyli na jedyne obiekty danego rodzaju, > > > np. true / false / nil. Te obiekty są niezmienialne, ale tożsamość > > > tych obiektów jest dobrze zdefiniowana; rozróżnianie ich po tożsamości > > > jest równoważne rozróżnianiu po cechach wewnętrznych. > > > > Nie tworzyłbym specjalnej kategorii dla tych obiektów. > Zwykle można je traktować razem z wartościowymi. Różnica objawia > się tylko wtedy, kiedy w języku mamy do dyspozycji operację jawnie > porównującą dwa obiekty po tożsamości. Tę operację można uznać za > niskopoziomową i rzadko się jej wprost używa, ale w wielu językach > jest dostępna, bo może być tańsza od domyślnego porównania, a dla > pewnego zbioru obiektów jest mu równoważna (Lisp: EQ, Scheme: eq?, > Python: is, Kogut: Is, OCaml: ==). Na przykład w Pythonie porównanie > "x is None" jest praktyczne, a "x is 5" nie jest. Qrczak - to wszystko prawda, ale to wciąż nie zmienia faktu: Obojętnie, jak mamy zaimplementowany sposób porównania wartości i tożsamości, obojętnie też, czy typ jest wartościowy, czy obiektowy, dla każdego typu istnieje tylko i wyłącznie jeden sensowny sposób porównania. Skoro tak, to nie potrzebujemy osobnych operatorów porównania - powinien być dostępny jeden operator porównania. > > > Jeśli spróbować dopasować do tego modelu C++, to się okaże, że zmienną > > > C++ zawierającą obiekt można rozumieć na dwa sposoby: > > > > > a) Jako zmienialny obiekt, przywiązany na stałe do swojej nazwy. > > > To tłumaczenie jest odpowiednie w przypadku obiektów z tożsamością, > > > zwłaszcza złożonych, bo pozwala wymodelować możliwość zmiany > > > indywidualnych pól obiektu z zachowaniem tożsamości całego obiektu. > > > Takie obiekty są zwykle przekazywane przez referencje C++ albo > > > wskaźniki C++, co odpowiada przekazaniu wskaźnika na obiekt > > > w modelu, a więc odpowiada naturalnemu sposobowi przekazania > > > wartości w modelu. > > > > > b) Jako zmienną zawierającą wartość, która sama jest niezmienialna. > > > To tłumaczenie jest lepsze dla atomowych typów wartościowych, > > > bo pozwala wymodelować wartość wyabstrahowaną od miejsca > > > przechowywania. Takie obiekty są w C++ zwykle kopiowane, > > > co odpowiada przekazaniu odczytanej bieżącej wartości zmiennej > > > w modelu, czyli znowu jest naturalnym sposobem przekazania wartości, > > > mimo że w C++ jest inne niż tamto. > > > > Szczerze mówiąc to nic z tego nie rozumiem. > Bo opisałem odpowiedniki zmiennej w C++ językiem (ludzkim) > przystosowanym do opisywania innych języków (programowania). > Jesteś przyzwyczajony do języka (ludzkiego) przystosowanego > do opisywania C++. Nie do końca się zgodzę, w szczególności nie zgodzę się, że opisałeś to językiem ludzkim :) > Jeśli w C++ mamy zmienną zawierającą obiekt udostępniający jakieś metody > (w tym metody zmieniające jego stan), to w innym języku odpowiednik tej > konstrukcji wygląda z reguły na jeden z dwóch sposobów, zależnie od > stylu, w jakim przeważnie wygodnie jest używać obiektów danego typu: > a) Typowy przykład: tablica. > Zmienna wskazuje na obiekt udostępniający analogiczne operacje jak > w C++. Obiekt jest tworzony na stercie. Do tej zmiennej nie jest > nigdy przypisywany wskaźnik na inny obiekt. Ale mówisz o tablicy surowej, tworzonej jako zmienna lokalna w funkcji. Pomówmy raczej o vectorze. > Tam, gdzie w C++ obiekt jest przekazywany przez referencję, w innym > języku przekazywana jest wartość tej zmiennej (wskazująca na ten > obiekt). Tam, gdzie w C++ obiekt jest przekazywany przez wartość, > w innym języku obiekt jest klonowany (czymś w rodzaju metody Clone). Tak - pod warunkiem, że pozwala się na klonowanie obiektów. > b) Typowy przykład: liczba. > Zmienna wskazuje na niezmienialny obiekt innego języka reprezentujący > bieżący stan obiektu C++. Metodom C++, które zmieniały stan obiektu, > odpowiadają operacje zwracające nowy obiekt, który jest przypisywany > z powrotem tej zmiennej. Pod warunkiem, że mamy możliwość "zakodowania" przypisania do zmiennej trzymającej ten niezmienialny obiekt. Tak zresztą jest to w Javie i Javowe rozwiązanie ma tylko jedną wadę: operator porównania :). > Tam, gdzie w C++ obiekt jest przekazywany przez wartość, w innym > języku przekazywana jest bieżąca wartość zmiennej. Tam, gdzie > w C++ obiekt jest przekazywany przez referencję, w innym języku > przekazywana jest referencja na zmienną. A co z porównywaniem? > > String zawsze powinien być traktowany jak wartość, natomiast wektor zawsze > > jak obiekt. > Zgodzę się, że zazwyczaj. Nie zgadzam się, że zawsze. Zgodzę się co najwyżej, że nie zawsze, tzn. wektor może służyć jako szczegół implementacyjny jakiegoś typu wartościowego. Ale nie sam wektor, bo to jest mniej więcej coś takiego jak void* do przechowywania dynamicznych danych. > A wektor znaków? Z jednej strony to jest wektor. Z drugiej strony to > jest w zasadzie to samo, co string. Różnica polega na tym, czym się różni "to samo" od "w zasadzie to samo" ;) Nie, Qrczak. String to nie jest tablica znaków - jak już się czepiamy skrzywionego myślenia, to i ja się poczepiam: twoje myślenie jest skrzywione przez języki, w których string jest reprezentowany przez listę znaków (jak np. Haskell). String charakteryzuje się tym, że posiada wartość; napis jest po prostu jednym napisem, który może być taki sam jak inny lub różny od niego, napisy możemy też porządkować po wartości (bo mają wartość), "ten sam napis" oznacza nam napis składający się z dokładnie takich samych znaków w tej samej kolejności. Vector natomiast jest zbiorem elementów - ich kolejność nie jest często specjalnie istotna (jeśli już, to najwyżej kwestie uporządkowany-nieuporządkowany), elementy często przestawia się w inne miejsce, wykonuje się często operacje na każdym elemencie po kolei. W przypadku stringa te operacje są w mniejszości, a sortowanie znaków w stringu uważałbym za powiew ezoteryki. To nie jest kwestia implementacji (string, vector), tylko kwestia logiki programu. Jasne, możemy sobie obsługiwać napisy jako vector<char>, ale to będą dla nas i tak napisy (język C przecież i tak obsługuje napisy jako tablice znaków). Implementacja jest więc nieistotna - ważne jest to, co to dla nas oznacza w programie. Dlatego dobre języki programowania pozwalają na stworzenie osobnych typów, które mają nawet wspólne podstawy implementacyjne, ale które logicznie oznaczają zupełnie co innego. Właśnie dlatego, że to narzuca nam sposób operowania takim typem. Można tablicę char'ów używać jako zbiór znaków i jako napis, oczywiście. Ale wtedy trzeba samemu pamiętać o tym, co jest czym i jak co mamy traktować. Jeśli język jest słaby i nie potrafi dać możliwości rozróżnienia tych rzeczy po statycznym typie (jak w C), to musi jakoś zapewnić możliwość alternatywnych sposobów porównań za pomocą osobnych operacji. > Różnice są w dodatkowych metodach, > ale one są raczej poboczne, nie wpływają na istotę rzeczy. Dobrze, Qrczak, niech ci już będzie, bo w tym momencie ręce mi opadły. > > > Pisałem tutaj o zmienialnym stringu, zakładając, że to jest jedyny > > > string w danym języku. Czyli kiedy złożony typ pełniący rolę typu > > > wartościowego jest jednak zmienialny. Taka sytuacja jest kłopotliwa. > > > > Oj... nie bardzo to widzę. > No i właśnie mówię, że to jest kłopotliwe. Lepiej tego unikać. > W to C++ pasuje. Tak, ale w C++ zmiana stringa zmienia tylko tą zmienną, która aktualnie przechowuje wartość. Inaczej mówiąc, nadaje nową wartość zmiennej. Można też odnieść się częściowo do tego, że niektóre implementacje stringa współdzielą tablicę znaków. Więc dwie różne zmienne mogłyby wskazywać na różne tablice, co bardzo przypominałoby wskazywanie na dwa obiekty przez dwie zmienne referencyjne. Ale w takim przypadku przydałoby się też jakieś sprytne COW, które by powodowało, że w razie zmiany przez jedną z tych zmiennych, każda z nich będzie miała od teraz własną kopię. Inaczej mówiąc, nawet jeśli jakaś zmienna współdzieli obiekt tablicy z innymi zmiennymi, to modyfikacja tej zmiennej nie zmienia wartości w pozostałych zmiennych (a jedynie traci z nimi powiązanie). > Przykłady języków, które mają wyłącznie zmienialne stringi mimo > paradygmatu, który do tego nie pasuje: Lisp, Scheme, OCaml, Ruby > (czasem są zmienialne łącznie ze zmianą długości, a czasem nie). Tzn. jak? Musisz jawnie skopiować string, jeśli chcesz, żeby źródłowy się nie zmienił? -- // _ ___ 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"
Re: Wartości i obiekty
Author: Marcin 'Qrczak' Kowalczyk
Date: Sun, 11 Mar 2007 22:15
Date: Sun, 11 Mar 2007 22:15
111 lines
6534 bytes
6534 bytes
Dnia 11-03-2007, nie o godzinie 15:29 +0000, Sektor van Skijlen
napisał(a):
> Obojętnie, jak mamy zaimplementowany sposób porównania wartości i tożsamości,
> obojętnie też, czy typ jest wartościowy, czy obiektowy, dla każdego typu
> istnieje tylko i wyłącznie jeden sensowny sposób porównania.
To jest prawie prawda.
Po pierwsze, co tłumaczę od paru postów, zdarza się, że typ ma
niejednoznaczny charakter i czasem jest używany w roli typu
wartościowego, a czasem typu z tożsamością. Zgadzam się, że to
jest kłopotliwe, ale to bywa faktem.
Po drugie czasem (rzadko) chcemy porównać tożsamość obiektów typów
wartościowych dla niskopoziomowych optymalizacji. Na przykład jeśli
rekurencyjna funkcja przekształcająca drzewo ma tę własność, że dla
wielu podfragmentów wynikiem jest sam argument, to można uniknąć
alokacji węzła wyniku w sytuacji, kiedy wywołania rekurencyjne nic nie
zmieniły i my też nie zamierzamy nic zmieniać. Przykład funkcji o tej
własności: uproszczenie wyrażenia algebraicznego.
Po trzecie są relacje, które - jeśli się uprzeć - można nazwać inaczej
niż równość, ale potocznie są to jakieś odmiany równości. Na przykład
sprawdzenie, czy dwa ciągi mają równe odpowiadające sobie elementy, bez
sprawdzenia, czy te ciągi w ogóle są tego samego typu.
Po czwarte tradycyjna równość zmiennoprzecinkowa nie jest relacją
równoważności (z powodu NaN) ani nie jest zachowywana przez operacje
arytmetyczne (z powodu -0.0). Jest więc powód, żeby traktować ją jako
osobną operację niż podstawowa równość.
A to jeszcze nie wszystko.
> > a) Typowy przykład: tablica.
>
> > Zmienna wskazuje na obiekt udostępniający analogiczne operacje jak
> > w C++. Obiekt jest tworzony na stercie. Do tej zmiennej nie jest
> > nigdy przypisywany wskaźnik na inny obiekt.
>
> Ale mówisz o tablicy surowej, tworzonej jako zmienna lokalna w funkcji.
>
> Pomówmy raczej o vectorze.
Miałem na myśli vector (tworzony jako zmienna lokalna w funkcji).
> > w innym języku obiekt jest klonowany (czymś w rodzaju metody Clone).
>
> Tak - pod warunkiem, że pozwala się na klonowanie obiektów.
Zawsze "się pozwala", bo nie ma czego zabraniać - to jest operacja jak
każda inna, jeśli się nie oczekuje, że będzie automatycznie dostępna
dla dowolnego typu.
> > b) Typowy przykład: liczba.
>
> > Zmienna wskazuje na niezmienialny obiekt innego języka reprezentujący
> > bieżący stan obiektu C++. Metodom C++, które zmieniały stan obiektu,
> > odpowiadają operacje zwracające nowy obiekt, który jest przypisywany
> > z powrotem tej zmiennej.
>
> Pod warunkiem, że mamy możliwość "zakodowania" przypisania do zmiennej
> trzymającej ten niezmienialny obiekt.
Jasne; miałem na myśli imperatywną, przypisywalną zmienną. Słowo
"zmienna" jest niestety wieloznaczne i część języków programowania,
tak jak matematyka, używa go w znaczeniu lokalnej nazwy jakiejś
wartości, niekoniecznie zmieniającej się w czasie.
> > Tam, gdzie w C++ obiekt jest przekazywany przez wartość, w innym
> > języku przekazywana jest bieżąca wartość zmiennej. Tam, gdzie
> > w C++ obiekt jest przekazywany przez referencję, w innym języku
> > przekazywana jest referencja na zmienną.
>
> A co z porównywaniem?
Nie rozumiem pytania. Dla obiektów tej kategorii porównanie jest dość
podstawową operacją, zdefiniowaną zależnie od typu. No i normalnie jest
oferowane, najczęściej w formie wspólnego interfejsu dla różnych typów.
> Nie, Qrczak. String to nie jest tablica znaków - jak już się czepiamy
> skrzywionego myślenia, to i ja się poczepiam: twoje myślenie jest skrzywione
> przez języki, w których string jest reprezentowany przez listę znaków (jak np.
> Haskell).
Etam. W C string też jest w zasadzie tablicą znaków, a w C++ mało do
tego brakuje. Szablon basic_string jest nawet parametryzowany typem
znaku. Ten typ ma trochę więcej wymagań niż typ elementu wektora, ale
poza tym różnica jest mała.
W Kogucie, podobnie jak w Pythonie i Perlu, w ogóle nie ma osobnego
typu znakowego. Kiedy znak jest materializowany w programie, jest
reprezentowany przez string długości 1. Na pewno więc string jako
tablica znaków nie jest moim skrzywieniem.
> > Przykłady języków, które mają wyłącznie zmienialne stringi mimo
> > paradygmatu, który do tego nie pasuje: Lisp, Scheme, OCaml, Ruby
> > (czasem są zmienialne łącznie ze zmianą długości, a czasem nie).
>
> Tzn. jak? Musisz jawnie skopiować string, jeśli chcesz, żeby źródłowy się nie
> zmienił?
Tak. Nie jest to aż tak błędogenne, jak mogłoby się wydawać, jeśli się
stosuje konwencję, że zmienia się tylko te stringi, które się przed
chwilą utworzyło. Czyli string jest w zasadzie traktowany jako typ
niezmienialny, imperatywne jest tylko jego tworzenie.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Re: Wartości i obiekty
Author: Sektor van Skijlen
Date: Mon, 12 Mar 2007 21:28
Date: Mon, 12 Mar 2007 21:28
251 lines
14011 bytes
14011 bytes
Dnia Sun, 11 Mar 2007 23:15:23 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 11-03-2007, nie o godzinie 15:29 +0000, Sektor van Skijlen > napisał(a): > > Obojętnie, jak mamy zaimplementowany sposób porównania wartości i tożsamości, > > obojętnie też, czy typ jest wartościowy, czy obiektowy, dla każdego typu > > istnieje tylko i wyłącznie jeden sensowny sposób porównania. > To jest prawie prawda. > Po pierwsze, co tłumaczę od paru postów, zdarza się, że typ ma > niejednoznaczny charakter i czasem jest używany w roli typu > wartościowego, a czasem typu z tożsamością. Zgadzam się, że to > jest kłopotliwe, ale to bywa faktem. A ja również tłumaczę od paru postów, że na taką okoliczność powinny zostać stworzone osobne typy statyczne. To prawda, że możesz używać tego samego typu języka jako logicznego typu wartościowego i niewartościowego, tyle że to sprowadza język do niskopoziomowego rozwiązania, w którym tego samego typu można używać do przechowywania logicznie różnych rzeczy. Jeśli mamy język taki, jak C, to rozumiem, że za bardzo nie mamy wyjścia. Dlatego tam używa się tego samego typu - tablicy char - jako łańcucha tekstowego i jako tablicy o elementach typu char. Natomiast dla języka wysokopoziomowego to po prostu wstyd, żeby nie zrobić tego na osobnych typach. Rozumieli to zarówno twórcy C++, jak i Javy, i C# (nb. Tcl-a też, dlatego też tam trzeba stosować pewne myki, żeby móc przekształcić napis na listę znaków). Najwyraźniej nie zrozumieli tego twórcy języków Haskell i D. Jeśli taki typ ma osobne specyfiki dla różnych przypadków, to i tak przynajmniej jednej specyfiki zawsze trzyma się jeden obiekt (czyli nie zmienia się nagle z typu obiektowego w wartościowy w trakcie działania). Jeśli tak, to można użyć osobnych definicji typów dla każdego obiektu używającego określonej specyfiki. > Po drugie czasem (rzadko) chcemy porównać tożsamość obiektów typów > wartościowych dla niskopoziomowych optymalizacji. Rozumiem - ale taka niskopoziomowa optymalizacja powinna być operacją szczególnego rodzaju, być dostępna tylko dla operacji bezpośrednio operujących na takim typie (lub specjalnie do tego dozwolonych), a przynajmniej powinna być wykonywalna za pomocą osobnych funkcji porównania. Nie chodzi mi przecież o to, żeby całkowicie zabronić możliwości sprawdzania tożsamości obiektów typów wartościowych. Chodzi o to, żeby każdy typ posiadał operator porównania, który porównuje w sposób adekwatny do rodzaju typu. > Po trzecie są relacje, które - jeśli się uprzeć - można nazwać inaczej > niż równość, ale potocznie są to jakieś odmiany równości. Na przykład > sprawdzenie, czy dwa ciągi mają równe odpowiadające sobie elementy, bez > sprawdzenia, czy te ciągi w ogóle są tego samego typu. Można, owszem, ale to nie jest porównanie wartości, tylko porównanie zawartości zbiorników (operacja specyficzna dla zbiornika, bo nie da się takiej operacji uogólnić na "po prostu obiekt"). Powinna być zatem dozwolona, ale jako specyficzna operacja, a nie porównanie. Dlaczego w C++ zbiorniki nie posiadają zdefiniowanego operatora porównania, tylko tego typu porównania wykonuje się algorytmami equal i mismatch? > Po czwarte tradycyjna równość zmiennoprzecinkowa nie jest relacją > równoważności (z powodu NaN) ani nie jest zachowywana przez operacje > arytmetyczne (z powodu -0.0). Jest więc powód, żeby traktować ją jako > osobną operację niż podstawowa równość. Nie no równość wartości zmiennoprzecinkowych to jest już osobna bajka. Jest to drobny wyłom w systemie typów wartościowych/obiektowych. Problem jest właśnie z tym NaN, bo gdyby nie to, to jeszcze na upartego zachowałaby się zasada, że wartość a skopiowana z b jest równa b. Nie wiem w tym momencie, czy typy zmiennoprzecinkowe można traktować jak wartości. Dla mnie najsensowniejszym rozwiązaniem byłoby zdefiniowanie jako operatora porównania porównania "wewnętrznego", czyli z zachowaniem zależności między przypisaniem a porównaniem. Natomiast osobno do tego należałoby stworzyć funkcję porównującą dwie liczby zmiennoprzecinkowe z zadanym epsilonem. Ci, co wymyślili ten numer z NaN, najwyraźniej nie zdawali sobie sprawy z tego, jakie zamieszanie tym zrobią. Zastanawiam się nawet, czy nie byłoby znacznie sensowniejsze uznanie liczb zmiennoprzecinkowych za typy niewartościowe. Tożsamość przez obiekt lepiej by się dla nich sprawdzała. > A to jeszcze nie wszystko. No to co jeszcze? Przecież można by do tej wyliczanki dołożyć stringa, którego możesz porównywać np. bez case'a, z pominięciem znaków kontrolnych itp. Powtarzam: nie zaprzeczam, że powinny być zdefiniowane różne metody porównywania dostępne dla danego obiektu, ale powinna być zawsze JEDNA operacja najwłaściwszego porównania zdefiniowana dla danego typu. > > > w innym języku obiekt jest klonowany (czymś w rodzaju metody Clone). > > > > Tak - pod warunkiem, że pozwala się na klonowanie obiektów. > Zawsze "się pozwala", bo nie ma czego zabraniać - to jest operacja jak > każda inna, jeśli się nie oczekuje, że będzie automatycznie dostępna > dla dowolnego typu. Niestety, bzdury opowiadasz. Istnieje coś takiego, jak unikalne wartości - wartość jednego pola, która w każdym obiekcie musi być inna. Często są to nawet obiekty generowane na rzecz innych, istniejących obiektów. Efekt jest taki, że żebyś mógł poprawnie tworzyć obiekt przez klonowanie, to musiałbyś podczas klonowania uwzględnić fakt, że wartości niektórych jego pól nie mogą być skopiowane, tylko muszą zostać wygenerowane na nowo. Czy taki obiekt będzie jeszcze klonem? Klonowanie zresztą to nie jest taka prosta sprawa. Pamiętam, jak w mudzie była funkcja klonująca moba. Trzeba było tam uwzględnić mnóstwo rzeczy: jeśli postać była wierzchowcem, to nowa postać była "nieosiodłana". Jeśli postać dosiadała wierzchowca, to nowa postać była tworzona na ziemi. Jeśli postać zajmowała mebel, to nowa postać musiała również stać obok (tzn. tak było po wniesieniu mojej poprawki do buga, bo poprzednio nowa postać była tworzona na tym samym meblu - autor najwyraźniej zapomniał, że meble mają też swoją pojemność i niekoniecznie dwie postacie będą mogły siedzieć na jednym krześle). Kolejnym problemem jest to, czy klonowanie postaci powinno pociągać za sobą klonowanie posiadanych przez nią przedmiotów, czy też nowa postać ma być stworzona "na golasa" (nie pamiętam już, jak to rozwiązano). Gdyby pociągać za sobą tworzenie przedmiotów, to dodatkowo niektóre mudy mają wprowadzoną ekonomię - czyli takie sklonowanie pociąga za sobą dodatkowo deflację. I tak można by wyliczać bez końca. Co więcej, często źródłem danych dla tworzenia nowego obiektu są jakieś specyficzne dane, które trzeba odpowiednio pobrać (być może zarejestrować, skojarzyć z czymś). W takim przypadku nie da się stworzyć obiektu na podstawie danych z innego obiektu, bo dane, które posiada ten hipotetyczny obiekt źródłowy są przygotowane tylko i wyłącznie dla niego. Jak ty sobie wyobrażasz np. sklonowanie obiektu oznaczającego plik, gniazdo, sesję, czy zbiornik właścicielski (zbiornik z dynamicznie tworzonymi obiektami, które zbiornik posiada na własność, tzn. usuwa je razem ze sobą)? Więc co oznacza "zawsze się pozwala"? Nie mówiąc o tym, że w dalszej części zdania twierdzisz, że można zabronić, więc nie rozumiem... > > > b) Typowy przykład: liczba. > > > > > Zmienna wskazuje na niezmienialny obiekt innego języka reprezentujący > > > bieżący stan obiektu C++. Metodom C++, które zmieniały stan obiektu, > > > odpowiadają operacje zwracające nowy obiekt, który jest przypisywany > > > z powrotem tej zmiennej. > > > > Pod warunkiem, że mamy możliwość "zakodowania" przypisania do zmiennej > > trzymającej ten niezmienialny obiekt. > Jasne; miałem na myśli imperatywną, przypisywalną zmienną. Słowo > "zmienna" jest niestety wieloznaczne i część języków programowania, > tak jak matematyka, używa go w znaczeniu lokalnej nazwy jakiejś > wartości, niekoniecznie zmieniającej się w czasie. Wiem, o co chodzi ze zmienną w obu przypadkach. Problem tylko w tym, czy język pozwala zrobić jakiś trik, który zakoduje operację modyfikującą obiekt tak, żeby wyglądała jak modyfikująca, a w rzeczywistości będzie tworzyć nową kopię obiektu. > > > Tam, gdzie w C++ obiekt jest przekazywany przez wartość, w innym > > > języku przekazywana jest bieżąca wartość zmiennej. Tam, gdzie > > > w C++ obiekt jest przekazywany przez referencję, w innym języku > > > przekazywana jest referencja na zmienną. > > > > A co z porównywaniem? > Nie rozumiem pytania. Dla obiektów tej kategorii porównanie jest dość > podstawową operacją, zdefiniowaną zależnie od typu. No i normalnie jest > oferowane, najczęściej w formie wspólnego interfejsu dla różnych typów. No właśnie. A co z implementacją? > > Nie, Qrczak. String to nie jest tablica znaków - jak już się czepiamy > > skrzywionego myślenia, to i ja się poczepiam: twoje myślenie jest skrzywione > > przez języki, w których string jest reprezentowany przez listę znaków (jak np. > > Haskell). > Etam. W C string też jest w zasadzie tablicą znaków, Ale Haskel, w odróżnieniu od C, nie jest językiem niskopoziomowym, z siermiężnymi właściwościami umożliwiającymi ledwie co zrobienie struktur, żeby jakoś operować własnymi typami. > a w C++ mało do > tego brakuje. Nawet jeśli można trochę ponaciągać fakty, żeby to stwierdzić, to nie zmienia faktu, że jednak zrobiono do tego osobne typy. > Szablon basic_string jest nawet parametryzowany typem > znaku. Complex też jest parametryzowany typem wartości zmiennoprzecinkowej, i co z tego? > Ten typ ma trochę więcej wymagań niż typ elementu wektora, ale > poza tym różnica jest mała. Różnica jest zasadnicza. Gdyby nie to, nikt by się nie silił na robienie osobnego typu dla stringa i vectora. Popatrz na język D - tam nie ma osobnego typu dla stringa, a string jest jednocześnie tablicą znaków (czyli, inaczej mówiąc, tablica znaków posiada całą funkcjonalność potrzebną dla stringa). > W Kogucie, podobnie jak w Pythonie i Perlu, w ogóle nie ma osobnego > typu znakowego. Kiedy znak jest materializowany w programie, jest > reprezentowany przez string długości 1. W Tcl-u też tak jest, więc to chyba nic niezwykłego jak na język skryptowy. > Na pewno więc string jako > tablica znaków nie jest moim skrzywieniem. Rozumiem, że musisz się jakoś bronić ;). Ale na poważnie - fakt, że w wielu językach string jest tożsamy z tablicą znaków, uważam za pomyłkę. Tablica znaków jest czymś koncepcyjnie innym od stringa, a jeśli coś jest koncepcyjnie inne, to system typów powinien pozwalać na wyrażenie tego osobnym typem. Język, który tego nie ma, ma "naleciałości asemblerowe". > > > Przykłady języków, które mają wyłącznie zmienialne stringi mimo > > > paradygmatu, który do tego nie pasuje: Lisp, Scheme, OCaml, Ruby > > > (czasem są zmienialne łącznie ze zmianą długości, a czasem nie). > > > > Tzn. jak? Musisz jawnie skopiować string, jeśli chcesz, żeby źródłowy się nie > > zmienił? > Tak. Nie jest to aż tak błędogenne, jak mogłoby się wydawać, jeśli się > stosuje konwencję, że zmienia się tylko te stringi, które się przed > chwilą utworzyło. Ależ jaja sobie robisz. Nie jest to aż tak błędogenne, jeśli się pamięta. Nie zapominaj, że bardzo często używasz tego argumentu przeciwko C++. > Czyli string jest w zasadzie traktowany jako typ > niezmienialny, imperatywne jest tylko jego tworzenie. Bardzo dobrze - ale niech w takim razie język sam zadba o to, żeby tego stringa nie dało się zmienić po jego utworzeniu. -- // _ ___ 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"
Re: Wartości i obiekty
Author: Sektor van Skijlen
Date: Tue, 13 Mar 2007 08:43
Date: Tue, 13 Mar 2007 08:43
17 lines
2013 bytes
2013 bytes
Dnia Mon, 12 Mar 2007 21:28:52 +0000 (UTC), Sektor van Skijlen skrobie: > > Szablon basic_string jest nawet parametryzowany typem > > znaku. > Complex też jest parametryzowany typem wartości zmiennoprzecinkowej, i co z > tego? Zapomniałem dopisać: Dlaczego complex ma swój własny osobny typ, zamiast żeby używało się do tego celu np. pair<double,double> ? -- // _ ___ 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"
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 10:16
Date: Wed, 21 Mar 2007 10:16
9 lines
1603 bytes
1603 bytes
Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> writes: [...] > O ile sobie przypominasz, wskazywałem ci już kiedyś, że jest możliwe > takie zorganizowanie wartości całkowitych, że każdej liczbie > odpowiada obiekt. Nawet cała klasa równoważności.
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 10:20
Date: Wed, 21 Mar 2007 10:20
10 lines
1776 bytes
1776 bytes
Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> writes: [...] > O ile sobie przypominasz, wskazywałem ci już kiedyś, że jest możliwe > takie zorganizowanie wartości całkowitych, że każdej liczbie > odpowiada obiekt. Nawet cała klasa abstrakcji zdefiniowana przez relację równoważności określoną na parach liczb naturalnych :>
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 10:24
Date: Wed, 21 Mar 2007 10:24
15 lines
1914 bytes
1914 bytes
Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> writes: [...] > Skoro tak, to nie potrzebujemy osobnych operatorów porównania - > powinien być dostępny jeden operator porównania. Hej, już chyba wiem, o co ci chodzi. Jedna relacja równości, a wiele relacji równoważności. Innymi słowy -- porównanie zawartości obiektów byłoby równoznaczne nie tyle z porównaniem tych obiektów, tylko ze sprawdzeniem zaistnienia pomiędzy tymi obiektami pewnej -- określonej przez programistę -- relacji równoważności. -- http://www.piotr.dembiński.prv.pl
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 10:28
Date: Wed, 21 Mar 2007 10:28
22 lines
2224 bytes
2224 bytes
pdemb@gazeta.pl (Piotr Dembiński) writes: > Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> > writes: > > [...] > >> Skoro tak, to nie potrzebujemy osobnych operatorów porównania - >> powinien być dostępny jeden operator porównania. > > Hej, już chyba wiem, o co ci chodzi. Jedna relacja równości, > a wiele relacji równoważności. Innymi słowy -- porównanie > zawartości obiektów byłoby równoznaczne nie tyle z porównaniem tych > obiektów, tylko ze sprawdzeniem zaistnienia pomiędzy tymi obiektami > pewnej -- określonej przez programistę -- relacji równoważności. Innymi słowy -- i może bardziej poprawnie -- sprawdzenia przez komputer, czy para sprawdzanych obiektów należy do klasy abstrakcji określonej na parach obiektów przez pewną relację równoważności. -- http://www.piotr.dembiński.prv.pl
Re: Wartości i obiekty
Author: Sektor van Skijlen
Date: Wed, 21 Mar 2007 12:39
Date: Wed, 21 Mar 2007 12:39
34 lines
2853 bytes
2853 bytes
Dnia Wed, 21 Mar 2007 11:28:28 +0100, Piotr Dembiński skrobie: > pdemb@gazeta.pl (Piotr Dembiński) writes: > > Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> > > writes: > > > > [...] > > > >> Skoro tak, to nie potrzebujemy osobnych operatorów porównania - > >> powinien być dostępny jeden operator porównania. > > > > Hej, już chyba wiem, o co ci chodzi. Jedna relacja równości, > > a wiele relacji równoważności. Innymi słowy -- porównanie > > zawartości obiektów byłoby równoznaczne nie tyle z porównaniem tych > > obiektów, tylko ze sprawdzeniem zaistnienia pomiędzy tymi obiektami > > pewnej -- określonej przez programistę -- relacji równoważności. > Innymi słowy -- i może bardziej poprawnie -- sprawdzenia przez > komputer, czy para sprawdzanych obiektów należy do klasy abstrakcji > określonej na parach obiektów przez pewną relację równoważności. O! Można to tak dokładnie określić. Oczywiście zakładając, że "klasa abstrakcji" jest określana przez jedną z właściwości dwóch obiektów. Przy takim założeniu zresztą te obiekty nawet mogą być różnych klas wyjściowych. -- // _ ___ 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"
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 15:25
Date: Wed, 21 Mar 2007 15:25
47 lines
3272 bytes
3272 bytes
Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid> writes: > Dnia Wed, 21 Mar 2007 11:28:28 +0100, Piotr Dembiński skrobie: >> pdemb@gazeta.pl (Piotr Dembiński) writes: > >> > Sektor van Skijlen >> > <ethouris@guess.if.gmail.com.is.valid.or.invalid> writes: >> > >> > [...] >> > >> >> Skoro tak, to nie potrzebujemy osobnych operatorów porównania - >> >> powinien być dostępny jeden operator porównania. >> > >> > Hej, już chyba wiem, o co ci chodzi. Jedna relacja równości, >> > a wiele relacji równoważności. Innymi słowy -- porównanie >> > zawartości obiektów byłoby równoznaczne nie tyle z porównaniem >> > tych obiektów, tylko ze sprawdzeniem zaistnienia pomiędzy tymi >> > obiektami pewnej -- określonej przez programistę -- relacji >> > równoważności. > >> Innymi słowy -- i może bardziej poprawnie -- sprawdzenia przez >> komputer, czy para sprawdzanych obiektów należy do klasy abstrakcji >> określonej na parach obiektów przez pewną relację równoważności. > > O! Można to tak dokładnie określić. > > Oczywiście zakładając, że "klasa abstrakcji" jest określana przez > jedną z właściwości dwóch obiektów. ZTCW to pojęcie klasy abstrakcji istnieje w matematyce i przynależy do algebry abstrakcyjnej, nie trzeba żadnego cudzysłowiu. > Przy takim założeniu zresztą te obiekty nawet mogą być różnych klas > wyjściowych. No ale po to definiujemy klasy, żeby odzwierciedlały pewne klasy abstrakcji. Plus można zawsze definiować klasy abstrakcji wewnątrz lub w poprzek klas zdefiniowanych w programie, poprzez określenie metod porównujących. Nawiasem mówiąc to kluczowa dla refaktoryzacji relacja równoznaczności (semantical equivalence) jest szczególnym przypadkiem relacji równoważności zdefiniowanej na tekstach programów komputerowych. -- http://www.piotr.dembiński.prv.pl
Re: Wartości i obiekty
Author: Piotr Dembiński
Date: Wed, 21 Mar 2007 15:31
Date: Wed, 21 Mar 2007 15:31
11 lines
1747 bytes
1747 bytes
pdemb@gazeta.pl (Piotr Dembiński) writes: [...] > Nawiasem mówiąc to kluczowa dla refaktoryzacji relacja > równoznaczności (semantical equivalence) jest szczególnym > przypadkiem relacji równoważności zdefiniowanej na tekstach > programów komputerowych. Oczywiście nie równoznaczności programów, tylko równoznaczności odniesień i działań programów.
Page 1 of 2 • 79 total messages
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads