Co to jest państwo, państwo zmienne i niezmienne?

32

To pytanie dla początkujących, ale nie mogłem znaleźć wystarczającej odpowiedzi dla początkujących w Google.

Co ludzie mają na myśli, mówiąc „stan” - ogólnie w programowaniu, a konkretnie w programowaniu OO?

Ponadto, czym jest stan zmienny i niezmienny - ponownie, ogólnie w programowaniu, a także w szczególności w OOP?

Aviv Cohn
źródło
4
Udostępnianie badań pomaga wszystkim . Powiedz nam, co próbowałeś i dlaczego nie spełnia twoich potrzeb. To pokazuje, że poświęciłeś trochę czasu, aby spróbować sobie pomóc, oszczędza nam to powtarzania oczywistych odpowiedzi, a przede wszystkim pomaga uzyskać bardziej konkretną i odpowiednią odpowiedź. Zobacz także How to Ask
zgryznij

Odpowiedzi:

46

Masz stan, kiedy kojarzysz wartości (liczby, ciągi, złożone struktury danych) z tożsamością i momentem.

Na przykład sama liczba 10 nie reprezentuje żadnego stanu: jest to tylko dobrze określona liczba i zawsze będzie sobą: liczba naturalna 10. Jako kolejny przykład ciąg „CZEŚĆ” jest ciągiem pięciu znaków, a jest to całkowicie opisane przez zawarte w nim znaki i kolejność ich pojawiania się. Za pięć milionów lat ciąg „CZEŚĆ” nadal będzie ciągiem „CZEŚĆ”: czysta wartość.

Aby mieć stan, musisz wziąć pod uwagę świat, w którym te czyste wartości są powiązane z jakimś rodzajem bytu, który posiada tożsamość . Tożsamość jest prymitywnym pomysłem: oznacza, że ​​możesz rozróżnić dwie rzeczy, niezależnie od jakichkolwiek innych właściwości, jakie mogą mieć. Na przykład dwa samochody tego samego modelu, tego samego koloru ... to dwa różne samochody.

Biorąc pod uwagę te rzeczy z tożsamością, możesz do nich przypisać właściwości, opisane czystymi wartościami. Na przykład mój samochód ma właściwość niebieskiego. Możesz opisać ten fakt, łącząc parę

("colour", "blue")

do mojego samochodu. Para („kolor”, „niebieski”) to czysta wartość opisująca stan tego konkretnego samochodu.

Stan jest powiązany nie tylko z konkretnym bytem, ​​ale także z określonym momentem w czasie. Można więc powiedzieć, że dzisiaj mój samochód ma stan

("colour", "blue")

Jutro przemaluję go na czarno i nowy stan będzie

("colour", "black")

Zauważ, że stan bytu może się zmienić, ale jego tożsamość nie zmienia się z definicji. Cóż, dopóki istota istnieje, oczywiście: samochód może zostać stworzony i zniszczony, ale zachowa swoją tożsamość przez całe życie. Mówienie o tożsamości czegoś, co jeszcze nie istnieje, nie ma sensu.

Jeśli wartości właściwości dołączonych do danej jednostki zmieniają się w czasie, mówisz, że stan tej jednostki jest zmienny . W przeciwnym razie mówisz, że państwo jest niezmienne .

Najczęstszą implementacją jest przechowywanie stanu bytu w pewnym rodzaju zmiennych (zmienne globalne, zmienne składowe obiektu), tj. Do przechowywania bieżącej migawki stanu. Zmienny stan jest następnie implementowany przy użyciu przypisania: każda operacja przypisania zastępuje poprzednią migawkę nową. To rozwiązanie zwykle używa lokalizacji pamięci do przechowywania bieżącej migawki. Zastąpienie lokalizacji pamięci jest destrukcyjną operacją, która zastępuje migawkę nową. ( Tutaj można znaleźć ciekawą rozmowę na temat tego podejścia do programowania zorientowanego na miejsce ).

Alternatywą jest przeglądanie kolejnych stanów (historii) bytu jako strumienia (być może nieskończonej sekwencji) wartości, patrz np. Rozdział 3 SICP . W takim przypadku każda migawka jest przechowywana w innym miejscu w pamięci, a program może jednocześnie badać różne migawki. Nieużywane migawki można zbierać, gdy nie są już potrzebne.

Zalety / wady obu podejść

  • Podejście 1 zużywa mniej pamięci i pozwala na bardziej efektywne tworzenie nowej migawki, ponieważ nie wymaga kopiowania.
  • Podejście 1 domyślnie wypycha nowy stan do wszystkich części programu zawierających odniesienie, podejście 2 potrzebowałoby jakiegoś mechanizmu do wypchnięcia migawki do swoich obserwatorów, np. W formie zdarzenia.
  • Podejście 2 może pomóc w zapobieganiu niespójnym błędom stanu (np. Częściowym aktualizacjom stanu): definiując jawną funkcję, która tworzy nowy stan ze starego, łatwiej jest odróżnić migawki tworzone w różnych momentach.
  • Podejście 2 jest bardziej modułowe, ponieważ umożliwia łatwe tworzenie widoków stanu, które są niezależne od samego stanu, np. Przy użyciu funkcji wyższego rzędu, takich jak mapi filter.
Giorgio
źródło
1
Zauważ, że obiekty nie są jedynymi elementami ze stanem. Jeśli program używa (zmiennych) zmiennych globalnych, sam program ma stan. Podobnie, jeśli funkcja ma zmienną, która zapamiętuje wartości w wywołaniach funkcji, funkcja jest stanowa.
Doval,
2
@Doval: Możesz myśleć o stanie globalnym jako stanie obiektu globalnego świata. O ile mi wiadomo, ten widok jest używany np. W Ruby. Funkcja zapamiętująca stan jest izomorficzna dla obiektu za pomocą tylko jednej metody. Wspólną podstawową ideą jest to, że kojarzysz wartości z tożsamościami lub miejscami, tzn. Że pewne rzeczy mogą przechowywać wartości (być może zmienne), ale zachowują swoją tożsamość.
Giorgio
3
Jasne, zgadzam się co do zasady. Po prostu upewniam się, że Prog rozumie, że stanowość nie jest czymś wyłącznym dla OOP. Nie sądzę, że linia myśli „wszystko jest przedmiotem” przychodzi naturalnie.
Doval,
@Doval: Wspomniałeś o stanowych funkcjach, które zapamiętują wartości w różnych wywołaniach. Jeden przykład, o którym mogę myśleć, to statyczne zmienne lokalne w C. Innym przykładem są zamknięcia (funkcje, które przechwytują zmienne zdefiniowane w ich kontekście). Zamknięcia są nieco dwojakie względem obiektów: zamknięcie to obiekt z dokładnie jedną metodą, podczas gdy obiekt jest zbiorem zamknięć zdefiniowanych za pomocą tych samych zmiennych. Prawdopodobnie wszystko to wiesz, ale chciałem to podsumować tutaj. Zasadniczo można przechowywać stan w pewnej lokalizacji pamięci i uzyskiwać do niego dostęp za pomocą różnych mechanizmów, jak wskazano.
Giorgio
11

Stan to po prostu informacja o czymś przechowywanym w pamięci.

Jako proste ćwiczenie zorientowania obiektowego, pomyśl o klasie jako o foremce do ciastek, a ciasteczka o obiektach. Możesz utworzyć plik cookie (utworzyć obiekt) za pomocą narzędzia do usuwania plików cookie (klasa). Powiedzmy, że jedną z właściwości ciasteczka jest jego kolor (który można zmienić za pomocą barwnika spożywczego). Kolor tego pliku cookie jest częścią jego stanu, podobnie jak inne właściwości.

Zmienny stan to stan, który można zmienić po utworzeniu obiektu (pliku cookie). Niezmienny stan to stan, którego nie można zmienić.

Niezmienne obiekty (dla których nie można zmienić żadnego stanu) stają się ważne, gdy mamy do czynienia z współbieżnością, czyli możliwością działania na tym obiekcie więcej niż jednego procesora w komputerze. Niezmienność gwarantuje, że możesz polegać na stanie, który jest stabilny i ważny przez cały okres istnienia obiektu.

Zasadniczo stan obiektu jest utrzymywany w „zmiennych prywatnych lub zmiennych członkowskich” i dostępny za pomocą „właściwości” lub metod getter / setter.

Robert Harvey
źródło
3
Z korzyścią dla Prog fakt, że wartość nigdy się nie zmienia, jest również ważny, ponieważ o wiele łatwiej jest o tym myśleć. Można go używać w dowolnej liczbie funkcji / metod i wiesz, że nie mogą go zmienić. W stanie zmiennym musisz śledzić historię wykorzystania tego obiektu, aby dowiedzieć się, jaka jest teraz jego wartość . To niepotrzebne obciążenie umysłowe, jeśli uczynienie go niezmiennym nie komplikuje programu.
Doval
Dzięki za odpowiedź. Zasadniczo w OOP, gdy ktoś mówi „stan”, zwykle oznacza „zmienne składowe obiektu”? Jeśli tak, to „stan zmienny” to zmienne publiczne, lub bardziej powszechne w OOP, zmienne prywatne, które można zmieniać metodami ustawiającymi - podczas gdy „stan niezmienny” to po prostu prywatne zmienne składowe?
Aviv Cohn,
1
Niezmienność można symulować , po prostu nigdy nie pisząc do prywatnych elementów obiektu, gdy zostaną one wypełnione wartościami początkowymi. Niezmienność może być wykonana przy użyciu wielu metod: nie zapewniając metody setter, wymagające wartość początkową należy ustawić za pomocą parametru konstruktora, pisanie w stylu funkcjonalnym, przy użyciu stałych, itp
Robert Harvey
1
Myślę o stanie jako wartości jakiejś własności jakiegoś bytu. „Wysłane” to stan. Podobnie jest z „stawką podatkową”. Waga czegoś jest stanem. To, czy obecnie nie śpisz, czy śpisz, jest stanem. Kolor czegoś jest stanem. Znacząca informacja o czymś, przechowywana w jakiejś pamięci komputera.
Robert Harvey
1
W wielu językach niezmienność może być wymuszona poprzez zadeklarowanie zmiennych składowych jako „const” lub „final”. Takie zmienne mogą być inicjowane tylko przez konstruktor. Nie zakładaj, że zmienne prywatne są niezmienne - nadal można je modyfikować za pomocą własnych funkcji (metod) klasy.
Simon B
7

Myślę, że termin „stan” (w przeciwieństwie do konkretnego typu stanu, takiego jak „zmienna składowa”) jest najbardziej użyteczny przy porównywaniu stanowego API z bezpaństwowym. Próba zdefiniowania „stanu” bez wspominania API jest trochę jak próba zdefiniowania „zmiennej” lub „funkcji” bez wspominania języków programowania; większość poprawnych odpowiedzi ma sens tylko dla osób, które już wiedzą, co oznaczają te słowa.

Stanowy a bezpaństwowiec

  • Stateful API to taka, która „zapamiętuje” jakie funkcje pan nazywa się tak daleko i jakie argumenty, więc następnym razem wywołania funkcji to będzie wykorzystywać te informacje. Część „zapamiętywanie” jest często implementowana ze zmiennymi składowymi, ale to nie jedyny sposób.
  • Bezpaństwowcem API jest jednym gdzie każdy wywołanie funkcji zależy wyłącznie od argumentów przekazanych do niego i nic więcej.

Na przykład OpenGL to prawdopodobnie najbardziej zaawansowany interfejs API, jaki znam. Jeśli mogę przez chwilę niedorzecznie uprościć to, możemy powiedzieć, że wygląda to tak:

glSetCurrentVertexBufferArray(vba1);
glSetCurrentVertexBufferObject(vbo1);
glSetCurrentVertexShader(vert1);
glSetCurrentFragmentShader(frag1);
// a dozen other things
glActuallyDrawStuffWithCurrentState(GL_TRIANGLES);

Prawie każda funkcja służy tylko do przejścia w stan, który musi zapamiętać OpenGL, a następnie na końcu wywołujesz jedną prostą funkcję antyklimatyczną, aby wykonać cały rysunek.

Bezstanowa wersja (nadmiernie uproszczonego) OpenGL prawdopodobnie wyglądałaby bardziej tak:

glActuallyDrawStuff(vba1, vbo1, vert1, frag1, /* a dozen other things */, GL_TRIANGLES);

Często słyszysz, jak ludzie mówią, że interfejsy API z mniejszym stanem są łatwiejsze do uzasadnienia. Jeśli możesz kontrolować liczbę argumentów, generalnie się z tym zgadzam.

Zmienny vs Niezmienny

O ile mi wiadomo, to rozróżnienie ma sens tylko wtedy, gdy można określić stan początkowy . Na przykład za pomocą konstruktorów C ++:

// immutable state
ImmutableWindow windowA = new ImmutableWindow(600, 400);
windowA = new ImmutableWindow(800, 600); // to change the size, I need a whole new window

// mutable state
MutableWindow windowB = new MutableWindow(600, 400);
windowB.width = 800; // to change the size, I just alter the existing object
windowB.height = 600;

Trudno byłoby zaimplementować klasę okna, która nie „pamięta” jej rozmiaru, ale możesz zdecydować, czy użytkownik powinien móc zmienić rozmiar okna po jego utworzeniu.

PS W OOP to prawda, że ​​„stan” zwykle oznacza „zmienne składowe”, ale może być o wiele więcej. Na przykład w C ++ metoda może mieć zmienną statyczną, a lambdas mogą stać się zamknięciami poprzez przechwytywanie zmiennych. W obu przypadkach zmienne te utrzymują się w wielu wywołaniach funkcji i dlatego prawdopodobnie kwalifikują się jako stan. Zmienne lokalne w funkcji regularnej można również uznać za stan w zależności od ich użycia (te, które mam w main (), często się liczą).

Ixrec
źródło
NIESAMOWITA odpowiedź. Dziękuję bardzo, naprawdę pomogłeś mi szybko to odebrać. Nie wiedziałem, że pracuję nad tym od dłuższego czasu i nie wiedziałem, jak to się nazywa.
the_endian
2

W laikach

Do słownika stany:

za. Stan lub sposób bycia, jak w odniesieniu do okoliczności.

  1. stan - sposób, w jaki coś jest w odniesieniu do jego głównych atrybutów;

Stan czegoś jest zbiorem wartości, które jego atrybuty mają w danym momencie.

W OOP stan obiektu jest migawką wartości jego atrybutów w danym momencie.

Thing t = new Thing();
t.setColor("blue");
t.setPrice(100)
t.setSize("small");

Jego stan to niebieski kolor, cena 100 i niewielki rozmiar.

Jeśli później:

t.setColor("red");

Zmieniasz jeden z jego atrybutów, ale zmieniłeś także cały stan, ponieważ obiekt nie jest już taki sam.

Czasami klasy są zaprojektowane tak, aby wartości ich właściwości nie mogły zostać zmienione po ich utworzeniu. Wszystkie wartości ich właściwości są albo przekazywane do konstruktora, albo odczytywane z jakiegoś źródła, takiego jak baza danych lub plik, ale po tym momencie nie ma możliwości zmiany tych wartości, ponieważ nie ma metod „ustawiających” ani żadnego innego sposobu zmiana wartości wewnątrz obiektu.

Thing t = new Thing("red",100,"small");
t.setColor("blue") -->> ERROR, the programmer didn't provide a setter or any other way to change the properties values after initialization.

To się nazywa stan, którego nie można zmienić zmutowanego. Wszystko, co możesz zrobić, to zniszczyć obiekt, utworzyć nowy i przypisać go do tego samego odwołania lub zmiennej.

Thing t = new Thing("red",100,"small");
t = new Thing("blue",100,"small");
// I had to create a new Thing with another color since this thing is inmutable.
Tulains Córdova
źródło