Mam doświadczenie w programowaniu w Javie, JavaScript i PHP.
Czytam Microsoft Visual C # 2010 krok po kroku, co moim zdaniem jest bardzo dobrą książką na temat zapoznania się z językiem C #.
Wydaje mi się, że mam problemy ze zrozumieniem statycznego słowa kluczowego. Z tego, co rozumiem do tej pory, jeśli klasa jest deklarowana jako statyczna, wszystkie metody i zmienne muszą być statyczne. Metoda główna zawsze jest metodą statyczną, więc w klasie, która istnieje metoda główna, wszystkie zmienne i metody są deklarowane jako statyczne, jeśli trzeba je wywołać w metodzie głównej. Zauważyłem również, że aby wywołać metodę statyczną z innej klasy, nie trzeba tworzyć obiektu, którego można użyć nazwy klasy.
Ale jaki jest rzeczywisty cel statycznego słowa kluczowego? Kiedy powinienem zadeklarować zmienną statyczną i metody?
źródło
Odpowiedzi:
Słowo „statyczne” w języku C # odnosi się do czegoś w klasie lub do samej klasy, które jest wspólne dla wszystkich instancji klasy. Na przykład, do pola oznaczonego jako statyczne można uzyskać dostęp ze wszystkich instancji tej klasy poprzez nazwę klasy.
Mogę szczerze powiedzieć, że nigdy nie korzystałem z klasy oznaczonej jako statyczna, z wyjątkiem tworzenia metod rozszerzania ( Szybki samouczek na temat metod rozszerzania ).
W każdym razie istnieją specyficzne wzorce projektowe do wykorzystania metod statycznych, takie jak wzorzec fabryczny i wzorzec singletonu , ale ważne jest, aby pamiętać, że metody statyczne i konstruktory nie zajmują się żadnym konkretnym wystąpieniem klasy (chyba że podasz jeden) zwykle w celu wykonania obliczeń lub porównania między obiektami. Metoda „główna”, do której się odwołujesz, jest zawsze statyczna, ale aby zobaczyć ją z innego punktu widzenia, zobacz ten artykuł .
Aby to kontynuować, oto jak nazywa się różnicę między metodami statycznymi i instancjami, polami i właściwościami.
Sprawdź także ten post , aby uzyskać głębsze spojrzenie na klasy statyczne.
źródło
Oto sposób na wyjaśnienie tego przez Joshua Blocha, który wydaje mi się genialny jak większość jego wypowiedzi (tak, jestem fanem Joshua Blocha :)). To jest cytowane z pamięci.
Wyobraź sobie, że klasa jest odpowiednikiem niebieskiego druku dla domu. Wyobraź sobie, że dom jest na niebiesko, jako instancja klasy dla klasy. Można z niej utworzyć jedną klasę (wydruk niebieski) i wiele instancji (domów).
Teraz zdrowy rozsądek mówi, że większość funkcji / zachowań, które dom (instancja) może mieć / wykonuje, nawet jeśli są zadeklarowane na niebiesko, nie można użyć, dopóki rzeczywisty dom (instancja) nie zostanie wykonany z tego niebieskiego -print (klasa). Na przykład twój niebieski wydruk może zawierać w nim miejsce, w którym powinny iść światła i żarówki, ale nie masz możliwości, aby działały na niebieskim druku, musisz faktycznie zbudować dom, aby móc włączanie i wyłączanie włącznika światła oraz włączanie i wyłączanie niektórych żarówek.
Jednak możesz mieć pewne zachowanie, które dotyczy bezpośrednio niebieskiego druku, i którego możesz użyć / uzyskać dostęp bezpośrednio na niebieskim wydruku, bez potrzeby tworzenia prawdziwego domu z tego niebieskiego wydruku. Wyobraź sobie, że twój niebieski nadruk ma przycisk, który po naciśnięciu wyświetli ślad domu zawarty w tym niebieskim nadruku (obliczając wszystkie długości ścian i tym podobne). Oczywiście MUSISZ najpierw zbudować dom, a potem odmierzyć jego powierzchnię, ale możesz to zrobić z samym niebieskim drukiem, więc bardziej pomocne byłoby wdrożenie tego zachowania w niebieskim druku. Taki osadzony na niebiesko przycisk, który oblicza powierzchnię domu, jest równoważny z funkcją statyczną w klasie.
źródło
Blueprint
klasę, która implementuje funkcjonalność planu, w tym zdolność do obliczania powierzchni domu wyrażonej przez plan. Ta instancja schematu jest następnie przekazywana doBuilder
(z kolei prawdopodobnie samej instancji), który z kolei robi to, co jest potrzebne do skonstruowania i wygenerowania potencjalnie dowolnej liczbyBuilding
instancji w oparciu o plan.Patrzenie na to w ten sposób pomaga mi:
Co do tego, kiedy użyć statycznego słowa kluczowego:
źródło
"Looking at it this way helps"
on. Uważasz to za dziwne, ponieważ nie jest to do końca prawda, ale możesz tak o tym myśleć, jeśli chcesz. Czy znasz model Bohr? Jest to zestaw reguł i pomysłów na to, jak atomy i elektrony oddziałują na siebie. Modelu pracuje w zależności od tego, co robisz, ale to nie jest rzeczywistość.static
nawet jeśli nie używa właściwości lokalnych. Tworzenie rzeczystatic
może dodać sprzężenie do klientów, ponieważ muszą oni bezpośrednio zwracać się do klasy. Na przykład może to utrudnić testowanie jednostkowe z kpiną.Najprostsze wyjaśnienie --- Statyczne => Dla jednego środowiska będzie istnieć tylko jedna kopia.
Tak więc w maszynie wirtualnej lub CLR będzie zawsze tylko jedna kopia klasy statycznej i każda inna klasa, do której się ona odwołuje, będzie musiała dzielić swoje metody i dane ze wszystkimi innymi klasami, które się do niej odwołują.
W przypadku zmiennej statycznej będzie istniała tylko jedna instancja tej zmiennej w środowisku wykonawczym, bez względu na to, ile kopii klasy właściciela jest utworzonych, gdy odwołują się do zmiennej statycznej, wszystkie będą odnosić się do tego samego elementu pamięci.
źródło
Członkowie statyczni są powiązani z klasą, a nie z żadną instancją tej klasy.
Ponieważ mówimy o .Net, rozważ klasę String , w szczególności metody Split i Join .
Split jest metodą instancji . Utwórz zmienną String, nadaj jej wartość, a następnie możesz wywołać Split () dla tej zmiennej / wartości i uzyskać tablicę „bitów”:
Tak więc, na przykład metody, wartość przechowywana w danej instancji klasy ma znaczenie .
Łączenie jest metodą statyczną . OK, to daje ciąg wynik podawany do separatora i tablicę ciągów do gryzienia, więc jest to „coś zrobić z” klasy String, ale to nie wiąże się z żadnym konkretnym wartości w dowolnej instancji String (rzeczywiście, wartości instancji są niedostępne dla metod statycznych).
W innych językach metoda Join mogła zostać „przyczepiona” do klasy Array (lub, być może lepiej, klasy StringArray), ale nasi przyjaciele z Redmond zdecydowali, że jest bardziej „odpowiednia” dla klasy String, więc umieścili ją tam .
Inną alternatywą może być zastosowanie metody Join instancji , w której wartość przechowywana w String [instancja klasy] służyła nam jako ogranicznik łączenia, coś w stylu:
źródło
Słowo
static
kluczowe może być trochę trudne do zrozumienia dla początkujących. Jego podstawowym celem jest identyfikacja członka klasy, który nie należy do żadnej pojedynczej instancji klasy, ale zamiast do samej klasy.Bez wchodzenia w zbyt wiele szczegółów, C # (i Java) sztywno egzekwują zorientowany obiektowo ideał, że cały kod i dane muszą należeć do obiektu, a zatem mają ograniczony zakres, widoczność i żywotność. Jest to ogólnie najlepsza praktyka wszędzie tam, gdzie ma zastosowanie podstawowa zasada obiektu reprezentującego jakąś rzeczywistość. Jednak nie zawsze; czasami potrzebna jest funkcja lub zmienna, do której można uzyskać dostęp z dowolnego miejsca w kodzie, bez konieczności przekazywania odniesienia do obiektu zawierającego ją, a także z gwarancją, że dane, które oglądasz lub zmieniasz, są dokładnie tym , co wszyscy else ma do czynienia, a nie jego kopię należącą do innej instancji obiektu.
Takie zachowanie było dostępne w C i C ++ w postaci funkcji lub zmiennej „globalnej”, która nie została zamknięta w obiekcie. Tak więc, jako kompromis, C # i Java obsługują „zakres statyczny”, półmetka między prawdziwie globalnym kodem bez obiektu nadrzędnego i elementami instancji o ograniczonym zakresie.
Każdy „element kodu” (funkcja, właściwość, pole) zadeklarowany jako
static
wchodzi w zakres od pierwszego wiersza funkcji programumain()
i nie opuszcza go, dopókimain()
funkcja się nie zakończy. W zwykłym języku angielskim istnieje element statyczny i można go używać, dopóki program jest uruchomiony. Ponadto elementy statyczne są wywoływane przez wywoływanie ich jako członków samego typu, a nie członków jednej instancji tego typu:Dzięki temu elementy statyczne są widoczne dla każdego kodu, który ma wiedzę o typie, niezależnie od tego, czy wiedzą o jakimkolwiek pojedynczym wystąpieniu tego kodu.
Aby odpowiedzieć na twoje pytanie, podstawową zaletą oznaczenia czegoś jako statycznego jest to, że staje się on widoczny wszędzie tam, gdzie znany jest sam typ, niezależnie od tego, czy konsumujący kod ma lub może uzyskać instancję zawierającego obiekt. Istnieje również niewielka poprawa wydajności; ponieważ metoda ma zakres statyczny, może uzyskiwać dostęp tylko do innych elementów statycznych (tej samej klasy lub innych) i do wszystkiego, co jest przekazywane jako parametr. Dlatego środowisko wykonawcze nie musi rozpoznawać żadnego odwołania do bieżącej instancji obiektu zawierającego, tak jak zwykle w przypadku metody instancji w celu zapewnienia informacji o stanie specyficznych dla kontekstu.
Całe klasy można również oznaczyć statycznie; robiąc to, informujesz kompilator, że deklaracja klasy będzie składać się wyłącznie z elementów statycznych, a zatem nie może być utworzona. Jest to łatwy sposób na upewnienie się, że w pamięci jest jedna i tylko jedna kopia obiektu; uczyń klasę i wszystko w niej statycznym. Jednak bardzo rzadko jest to najlepsze rozwiązanie takiej potrzeby. W sytuacji, gdy wymagana jest dokładnie jedna kopia zestawu danych, zwykle zaleca się stosowanie „singletonu”; jest to klasa niestatyczna, która używa statycznego akcesora i niepublicznego konstruktora, aby zapewnić dostęp do pojedynczej instancji samego siebie. Teoretycznie singleton zapewnia te same korzyści, co klasa w pełni statyczna, ale z dodatkową możliwością korzystania z klasy w sposób obiektowy i obiektowy.
źródło