Właśnie jestem przy obiektach String i przy zamrażaniu. Zauważyłem, że jak się zamrozi obiekt
str = "const"
str,freeze
to concatować się nie da:
str.concat("variable")
wywali:
Tylko zastanawia mnie sens. Właściwie wszystko inne (na przykład):
str += " not"
zadziała. Wiem, że pod spodem podmianiają się tylko referencje do tworzonego na nowo obiektu - ale takie zarożenie, które tego nie bloku jest nic nie warte bo z jednej strony wiem, że to już nie jest ten sam obiekt, a z drugiej strony chciałem się obronić przed możliwością zmiany jego zawartości - a go straciłem… Czy freeze ma jakieś sensowne zastosowanie ?
Mylisz tutaj dwie rzeczy - niemodyfikowalność obiektu ze “stałością” zmiennej. W pierwszym przypadku nie możesz na obiekcie (do którego może przecież odnosić się wiele zmiennych) wywołać metody, która powoduje jego modyfikację (np. przypisuje nową wartość którejś z jego zmiennych instancyjnych). W drugim przypadku chodzi o to, że jakieś odniesienie (zmienna/stała?) nie może się zmienić, tzn. że raz przypisany do niej obiekt nie może zostać zastąpiony innym.
Pierwszy przypadek ilustruje następujący fragment kodu:
a = "Abc"
b = "Abc"
a.freeze
b.concat "zzz"
#=> Error
Czy da się jakoś osiągnąć drugi przypadek? Teoretycznie w Rubim występują stałe - zaczynają się od wielkiej litery. Ale… niestety można zmienić przypisaną do nich wartość. Bardzo wielu ludzi to denerwuje, mnie też. Interpreter wygeneruje tylko ostrzeżenie:
A = "a"
A = "b"
#=> warning: already initialized constant A
Zatem to co chciałbyś osiągnąć powinno być kombinacją freeze i użycia stałej, tyle, że niestety i tak nie daje nam to gwarancji, że ktoś nam tego nie zmieni… niestety. Miejmy nadzieje, że Matz w końcu uczyni ze stałych prawdziwe STAŁE.
No właśnie, też mnie uderzyło to, że stałe są zmienianlne - jak przeczytałem pierwszy raz o freeze to myślałem - no w końcu jednak się da, a tutaj kicha … Dzięki za wyjaśnienie. Oddaję się dalszej lekturze …
Freeze nie pozwala na zmianę in-place, na modyfikację danej instancji stringu. Natomiast nie ma wpływu na zmienną do której jest ona przypisany. A += tworzy nowy string i przypisuje go do starej zmiennej: