Jestem nowy w programowaniu obiektowym, a jedną z koncepcji, którą zajęło mi trochę czasu, jest niezmienność. Myślę, że żarówka zgasła ostatniej nocy, ale chcę zweryfikować:
Kiedy napotykam stwierdzenia, że niezmiennego obiektu nie można zmienić, jestem zdziwiony, ponieważ mogę na przykład wykonać następujące czynności:
NSString *myName = @"Bob";
myName = @"Mike";
Tam właśnie właśnie zmieniłem nazwę, niezmiennego typu NSString. Mój problem polega na tym, że słowo „obiekt” może odnosić się do fizycznego obiektu w pamięci lub abstrakcja „mojaNazwa”. Poprzednia definicja dotyczy pojęcia niezmienności.
Jeśli chodzi o zmienną, bardziej przejrzystą (dla mnie) definicją niezmienności jest to, że wartość niezmiennego obiektu można zmienić tylko poprzez zmianę jego położenia w pamięci, tj. Jego odniesienia (znanego również jako jego wskaźnik).
Czy to prawda, czy wciąż jestem zagubiony w lesie?
źródło
NSString
, to „ wskaźnik do iNSString
”, który nie jest niezmienny. I nic obiektywnego C wiem, ale zgaduję, że w swojej przykład@"Mike"
tworzy nową instancjęNSString
i przypisanie go do wskaźnika ,myName
. Więc nie zmieniłeś obiektu, którymyName
wskazywał, tylko to, na co wskazywał.Odpowiedzi:
Wygląda na to, że zmierzasz we właściwym kierunku, ale jeszcze go nie rozumiesz. To jest źle:
We fragmencie kodu
myName
nie jest on niezmiennyNSString
, jest typu zmiennegoNSString*
(wskaźnik do NSString). Wygląda na to, że kluczową rzeczą, której brakuje, jest zrozumienie, że wskaźnik jest po prostu inną wartością i ma całkowicie odrębne życie od rzeczy, na którą wskazuje (lub rzeczy, jeśli zmienisz go w trakcie jego życia).Mówisz:
To jest źle. Obiekt nie jest właścicielem wskaźników, które na niego wskazują, ani też lokalizacja pamięci obiektu nie jest kontrolowana ani w żaden inny sposób nie ma na nią wpływu.
Zatem dwa
NSString
obiekty w twoim przykładzie (@"Bob"
i@"Mike"
) są całkowicie oddzielone odmyName
zmiennej. Są również całkowicie oddzielone od siebie. Kiedy zmieniszmyName
na wskaż na@"Mike"
zamiast wskazywać na@"Bob"
, nie zmieniaszNSString
obiektów.Dla kompletności zwrócę uwagę na to, że zbieracze śmieci powodują, że jest to bardziej złożone, ponieważ zmiany wskaźników mogą wpływać na obiekty, na które wskazują (ed). Jest to jednak szczegół implementacji, który nie powinien wpływać na obserwowalne zachowanie kodu.
źródło
Jesteś zagubiony w słowach. Niezmienność oznacza: Dopóki nie zmienisz zmiennej, zawsze będzie ona „zawierać” tę samą wartość, bez względu na to, co zrobisz z innymi zmiennymi.
Kontrprzykład w C (nieco uproszczony, przy założeniu architektury, która to umożliwia):
Teraz już nie „zawiera” (tzn. Wskazuje na) ciąg „Hello World”, ale zamiast tego jest „Yello World”.
W językach, w których ciągi są niezmienne, takich jak Java i (EDIT: safe) C #, nie można tego zrobić. Nie ma mowy. Oznacza to, że każda część programu może bezpiecznie przechowywać odniesienie do łańcucha i polegać na tym, że jego zawartość nigdy się nie zmienia; w przeciwnym razie musieliby stworzyć kopię, aby być po bezpiecznej stronie.
Ale zmienna wciąż jest zmienna. Możesz pozwolić mu wskazywać inny obiekt. Tyle, że sam obiekt nie zmieni się za twoimi plecami.
źródło
unsafe
kodu.Mylisz zmienne z obiektami. Zmienne mogą być używane do przechowywania odniesień do obiektów, ale NIE są to obiekty. Są to obiekty, które są niezmienne, a nie zmienne, więc możesz zmienić zmienną z jednego obiektu na drugi, ale nie możesz zmienić atrybutów obiektu, jeśli jest niezmienny.
Pomyśl o tym obiekcie jak o głośnym, pijanym sąsiadu. Jeśli jest rozsądny (zmienny), być może będziesz w stanie zapukać do jego drzwi i przekonać go do stylu życia, w którym nie robi tyle hałasu. Ale jeśli jest niezmienny, jedyną zmianą jest nadzieja, że ktoś się wprowadzi!
źródło
Zmienna nie jest obiektem. Zmienna to nazwa, która odnosi się do obiektu (lub bardziej ogólnie wartości).
Na przykład „bramkarz” to nazwa, której używamy w odniesieniu do obiektu (osoby) odpowiedzialnej za obronę celu. Ale jeśli zastąpię tę osobę inną osobą (ponieważ ta pierwsza jest ranna lub coś w tym rodzaju), nowa osoba jest teraz nazywana „bramkarzem”.
Instrukcja przypisania powoduje, że zmienne są zmienne (niektóre języki, takie jak Haskell, nie mają go i faktycznie używają niezmiennych zmiennych). Pozwala przedefiniować znaczenie nazwy, a tym samym ponownie przypisać wartość.
Teraz same obiekty mogą być niezmienne. Kilka tysięcy lat temu można było pomyśleć o diamentach jako niezmiennych. Bez względu na to, co zrobiłeś z diamentem, nie możesz go zmodyfikować. Bez względu na to, czy nazwałeś go waggawooga (luźno oznacza to „największy błyszczący kamień naszego plemienia”), czy przestałeś go tak nazywać (ponieważ znalazłeś większy), diament pozostał ten sam. W przeciwieństwie do tego kawałek drewna, który rzeźbiłeś na zabawnych zdjęciach swoją waggawoogą, nie pozostał taki sam. Okazało się zmienne. Nawet jeśli miał przez cały czas tę samą nazwę.
Zarówno zmienne, jak i wartości mogą być niezmienne (niezależnie). W tym przypadku są to obiekty niezmienne. Po zbudowaniu
NSString
nie można go modyfikować. Możesz nazywać go imionami i przekazywać, ale pozostanie taki sam. W przeciwieństwie do tegoNSMutableString
można go zmienić po utworzeniu, na przykład przez wywołaniesetString
metody.źródło
Myślę, że czujesz się zagubiony, ponieważ łączysz dwie koncepcje: sam obiekt i nazwę zmiennej związaną z tym obiektem.
Niezmiennych obiektów nie można zmienić. Kropka. Jednak nazwa zmiennej (symbol) związana z niezmiennym obiektem, może zostać zmodyfikowana, aby była powiązana z innym niezmiennym obiektem.
Innymi słowy, to, co zrobiłeś w tych dwóch liniach, to:
myName
z tym obiektemmyName
z tym obiektemźródło
Twój preferowany typ nie jest to
NSString
, że jest to „ wskaźnik doNSString
”, który nie jest niezmienna. Nic nie wiem o celu C, ale zgaduję w twoim przykładzie, który@"Mike"
tworzy nową instancjęNSString
i przypisuje ją do wskaźnikamyName
. Więc nie zmieniły się obiekt, którymyName
został skierowany w celu, tylko co to wskazywał.źródło
Oto przykład zmiennego obiektu: tablica
char
w C:Mogę zmienić zawartość z
str
do treści mojego serca (tak długo, jak to jest nie więcej niż 10 znaków). Aby mógł zostać rozpoznany jako ciąg przez funkcje biblioteki ciągów C, musi mieć końcowe 0, aby mógł przechowywać ciągi o długości do 9 znaków:i tak weiter .
Porównaj to z obiektem łańcuchowym w Javie:
Instancja ciągu (fragment pamięci zawierający znaki „H”, „e”, „l”, „l” i „o”) nie może być modyfikowany; Nie mogę zmienić żadnej zawartości tego ciągu. Kiedy piszesz coś takiego
nie dołączasz „World” na końcu wystąpienia „Hello”; tworzysz nową instancję , kopiujesz do niej „Hello World” i aktualizujesz,
foo
aby odwoływała się do tej nowej instancji ciągu.foo
sam nie zawiera instancji ciągu; odnosi się tylko do tego wystąpienia (podobnie do wskaźnika w C lub Obj-C), dlatego typy takie jak String są nazywane typami referencyjnymi.źródło