Obiekty immutable, jak wskazuje ich nazwa, charakteryzują się tym, że nie można ich prosto zmienić po tym jak zostały stworzone (można na przykład dostać się do samej pamięci, czy też użyć refleksji). Nie ważne ile mają pól i właściwości oraz jakiego są typu. Czasem, potrzebujemy taki obiekt zmienić, wtedy zmieniamy go w całości. Możemy po prostu stworzyć nowy obiekt tej samej klasy mający nowe wartości.
Co nam to daje?
Zalet posiadania i używania takich obiektów jest kilka.
Gdy używamy niezmiennego obiektu, np przekażemy go w parametrze funkcji, lub w jakikolwiek sposób udostępnimy go innym obiektom czy metodom by na nim operowały, nie musimy się przejmować tym, że ktoś go zmieni celowo albo przypadkiem, nie będąc świadomym konsekwencji jakie to za sobą w naszym systemie niesie.
Jeśli inna klasa, albo programista w swoim kodzie chce użyć zmienionego obiektu, to nie zrobi tego „przypadkiem”. Nie ma innego wyjścia, jak utworzenie nowego obiektu i używanie tego nowego w dalszej części kodu.
Innymi słowy, cokolwiek metoda pracująca na obiektach niezmiennych nie zrobi, nie będzie powodować żadnych skutków ubocznych w kontekście obiektu niezmiennego.
Dokładnie tak samo jest z metodami znajdującymi się wewnątrz naszego obiektu. Prywatne czy publiczne, one też nie są w stanie go zmienić. Gdy np dopiszemy nową metodę, wiemy, że nie zmienimy samego obiektu, tym samym nie „zepsujemy” niczego w systemie, gdy jakaś inna metoda zostanie wywołana, czy to w tym samym czasie czy później. Ona może się spodziewać innego stanu obiektu. Jest to istotne np gdy programujemy równolegle.
I tak doszliśmy do drugiej zalety: takie obiekty świetnie sprawdzają się przy programowaniu rozproszonym. Kilka wątków może bezpiecznie pracować na takim niezmiennym obiekcie, bez martwienia się o spójność danych i deadlocki.
Dość łatwo i przyjemnie się też je testuje, skoro wiemy, że nic ich nie zmieni po ich utworzeniu, a co najwyżej ich metody mogą zwracać nowe obiekty.
Kiedy to podejście się nie sprawdza?
Nie znaczy to, że nagle każda klasa jaką tworzymy powinna być niezmienna. Często i gęsto nie potrzebujemy niezmienności, bo np nie programujemy w środowisku rozproszonym, a jeśli przestrzegamy zasad enkapsulacji i nie pozwalamy z zewnątrz zmieniać wszystkiego jak leci, to nie musimy się też zwykle martwić o brak spójności danych.
Większość systemów, lub jego części jest prosta i często obiekt wymaga zmiany jednego pola czy właściwości i tworzenie nowego z identycznymi wartościami w pozostałych może być niewydajne. Garbage Collector musi posprzątać po nas i usunąć stary obiekt, a pamięć dla nowego też zostanie zaalokowana na nowo. To przy niewielu i rzadkich zmianach nie będzie mieć żadnego znaczenia, ale przy wielu częstych już może spowodować spory spadek wydajności.
Może też po prostu wymagać napisania zbędnego, zaciemniającego obraz całości kodu (czyli np tego co my właściwie zmieniamy a co zostało takie samo).
kamagra