Jaka jest różnica między dwiema metodami UpdateSubject poniżej? Czułem, że stosowanie metod statycznych jest lepsze, jeśli chcesz po prostu operować na jednostkach. W jakich sytuacjach powinienem stosować metody niestatyczne?
public class Subject
{
public int Id {get; set;}
public string Name { get; set; }
public static bool UpdateSubject(Subject subject)
{
//Do something and return result
return true;
}
public bool UpdateSubject()
{
//Do something on 'this' and return result
return true;
}
}
Wiem, że otrzymam wiele kopnięć od społeczności za to naprawdę denerwujące pytanie, ale nie mogłem się powstrzymać od zadawania tego pytania.
Czy staje się to niepraktyczne w przypadku dziedziczenia?
Aktualizacja:
dzieje się teraz w naszym miejscu pracy. Pracujemy nad 6-miesięczną aplikacją asp.net z 5 programistami. Nasz architekt zdecydował, że stosujemy wszystkie metody statyczne dla wszystkich interfejsów API. Jego rozumowanie jako statyczne metody jest lekkie i przynosi korzyści aplikacjom internetowym, utrzymując obciążenie serwera na niskim poziomie.
źródło
Odpowiedzi:
Przejdę do najbardziej oczywistych problemów metod statycznych z wyraźnymi parametrami „to”:
Tracisz wirtualną wysyłkę, a następnie polimorfizm. Nigdy nie można zastąpić tej metody w klasie pochodnej. Oczywiście możesz zadeklarować metodę
new
(static
) w klasie pochodnej, ale każdy kod, który uzyskuje do niej dostęp, musi być świadomy całej hierarchii klas oraz wykonywać jawne sprawdzanie i rzutowanie, czego dokładnie powinien unikać OO .W pewnym sensie rozszerzenie nr 1 nie można zastąpić instancji klasy interfejsem , ponieważ interfejsy (w większości języków) nie mogą deklarować
static
metod.Niepotrzebna gadatliwość. Co jest bardziej czytelne:
Subject.Update(subject)
czy po prostusubject.Update()
?Sprawdzanie argumentów. Znowu zależy od języka, ale wielu skompiluje niejawne sprawdzenie, aby upewnić się, że
this
argument nie manull
na celu zapobieżenie stworzeniu przez błąd odniesienia zerowego niebezpiecznych warunków środowiska wykonawczego (rodzaj przepełnienia bufora). Nie korzystając z metod instancji, musisz jawnie dodać tę kontrolę na początku każdej metody.To jest mylące. Kiedy normalny, rozsądny programista zobaczy
static
metodę, będzie naturalnie zakładał, że nie wymaga ona prawidłowej instancji (chyba że wymaga wielu instancji, takich jak metoda porównania lub metoda równości, lub oczekuje się, że będzie w stanie działać nanull
referencjach) . Zobaczenie metod statycznych zastosowanych w ten sposób sprawi, że zrobimy podwójne, a może potrójne ujęcie, a po 4. lub 5. raz będziemy zestresowani i źli, a Bóg pomoże ci, jeśli znamy twój adres domowy.To forma powielania. To, co faktycznie dzieje się po wywołaniu metody instancji, polega na tym, że kompilator lub środowisko wykonawcze wyszukuje metodę w tabeli metod tego typu i wywołuje ją za
this
pomocą argumentu. Zasadniczo wdrażasz ponownie to, co kompilator już robi. Naruszasz DRY , powtarzając wielokrotnie ten sam parametr różnymi metodami, gdy nie jest to potrzebne.Trudno wyobrazić sobie dobry powód do zastąpienia metod instancji metodami statycznymi. Proszę nie.
źródło
File
,FileInfo
iDirectoryInfo
(aw rzeczywistości istnieją biblioteki, które ukrywają je za interfejsów, które mogą być następnie wstrzykiwane jako potrzebne i wyśmiewany w testach).Prawie opisałeś dokładnie, jak robisz OOP w C, w którym dostępne są tylko metody statyczne, a „this” jest wskaźnikiem struktury. I tak, można wykonać polimorfizm w czasie wykonywania w C, określając wskaźnik funkcji podczas budowy, który ma być przechowywany jako jeden element struktury. Metody instancji dostępne w innych językach to po prostu cukier składniowy, który zasadniczo robi dokładnie to samo pod maską. Niektóre języki, takie jak python, znajdują się w połowie drogi, gdzie parametr „self” jest wyraźnie wymieniony, ale specjalna składnia do jego wywoływania obsługuje dla ciebie dziedziczenie i polimorfizm.
źródło
obj->type->mthd(obj, ...);
i jest to zasadniczo podobne do tego, co dzieje się z wirtualną wysyłką w innych językach (ale za kulisami).Problem z metodą statyczną pojawia się w momencie, gdy potrzebujesz podklasy.
Metod statycznych nie można zastąpić w podklasach, dlatego nowe klasy nie mogą zapewnić nowych implementacji metod, co czyni je mniej użytecznymi.
źródło
Jeśli deklarujesz metodę
static
, nie musisz tworzyć instancji obiektu z klasy (używającnew
słowa kluczowego), aby wykonać metodę. Nie można jednak odwoływać się do żadnych zmiennych składowych, chyba że są one również statyczne, w którym to przypadku te zmienne składowe należą do klasy, a nie do określonego obiektu instancji klasy.Innymi słowy,
static
słowo kluczowe powoduje, że deklaracja jest częścią definicji klasy, więc staje się pojedynczym punktem odniesienia we wszystkich instancjach klasy (obiekty tworzone z klasy).Wynika z tego, że jeśli chcesz wielu uruchomionych kopii swojej klasy i nie chcesz, aby stan (zmienne składowe) był współużytkowany przez wszystkie uruchomione kopie (tj. Każdy obiekt ma swój własny unikalny stan), wtedy nie można zadeklarować tych zmiennych składowych jako statycznych.
Zasadniczo powinieneś używać
static
klas i metod tylko wtedy, gdy tworzysz metody narzędziowe, które akceptują jeden lub więcej parametrów i zwracają jakiś obiekt, bez żadnych skutków ubocznych (tj. Zmiany zmiennych stanu w klasie)źródło
static
znaczy, pyta, dlaczego nie zadeklarować wszystkiego jako statycznego.Subject
- ale jako wyraźną parametru, zamiast niejawnymthis
parametrem.this
parametru niejawnego . Nie ma różnic w oczekiwaniach, ale poza dziedziczenia, nie ma istotnej różnicy w tym, co można zrobić. Na przykład, do tych niestatycznych elementów członkowskich można uzyskać dostęp - za pomocą jawnego parametru.Powód, dla którego ludzie twierdzą, że „metody statyczne wykazują zły projekt” niekoniecznie wynika z metod, w rzeczywistości są to dane statyczne, niejawne lub jawne. Przez domniemany rozumiem DOWOLNY stan w programie, który nie jest zawarty w zwracanych wartościach lub parametrach. Modyfikowanie stanu w funkcji statycznej to powrót do programowania proceduralnego. Jeśli jednak funkcja nie modyfikuje stanu lub przekazuje modyfikację stanu do funkcji obiektu składowego, w rzeczywistości jest to bardziej funkcjonalny paradygmat niż proceduralny.
Jeśli nie zmieniasz stanu, metody statyczne i klasy mogą przynieść wiele korzyści. Znacznie ułatwia to, aby metoda była czysta, a zatem wolna od skutków ubocznych, a wszelkie błędy są w pełni powtarzalne. Zapewnia również, że różne metody w wielu aplikacjach korzystających ze wspólnej biblioteki mogą być pewne, że uzyskają te same wyniki przy tych samych danych wejściowych, co znacznie ułatwi zarówno śledzenie błędów, jak i testowanie jednostek.
Ostatecznie w praktyce nie ma różnicy między często przewymiarowanymi obiektami, takimi jak „StateManager”, a danymi statycznymi lub globalnymi. Zaletą prawidłowych metod statycznych jest to, że mogą one wskazywać na intencję autora, aby nie modyfikować stanu późniejszych korektorów.
źródło
making ... unit testing much easier.
Nie, nie będzie. To sprawia, że żaden kod wywołujący metody statyczne jest niemożliwy do testowania jednostkowego , ponieważ nie można go odizolować od metody statycznej. Wywołanie metody statycznej staje się na stałe zależną od tej klasy.W zależności od języka i tego, co próbujesz zrobić, odpowiedź może być taka, że nie ma dużej różnicy, ale
static
wersja ma nieco więcej bałaganu.Ponieważ twoja przykładowa składnia sugeruje, że Java lub C #, myślę, że Thorbjørn Ravn Andersen słusznie wskazuje na nadrzędny (z późnym wiązaniem) problem. W przypadku metody statycznej nie ma „specjalnego” parametru, na którym powinno się opierać późne wiązanie, więc nie można mieć późnego wiązania.
W efekcie metoda statyczna jest po prostu funkcją w module, który ma taką samą nazwę jak klasa - tak naprawdę wcale nie jest to metoda OOP.
źródło
W ten sposób pokonujesz cały punkt obiektów. Jest dobry powód, dla którego właściwie zmieniliśmy kod proceduralny na kod obiektowy.
Ja nigdy nie deklarują statyczną metodę, która miała typ klasy jako parametr. To tylko sprawia, że kod jest bardziej złożony bez żadnego zysku.
źródło
object
dostatic
sposobu i powrocie nowaobject
. Funkcjonalni programiści robią to cały czas.Math
klasę statyczną za „kompleks bez wzmocnienia”, czy wolałbyś, gdyby wszystkie typy liczb miały metody wirtualne określające wartość bezwzględną, negację, dodawanie, kwadratowanie, arbitralne pierwiastki i tak dalej? Nie wydaje mi się obiekty są schludne, gdy trzeba przechowywać ukryty zmienny stan, w którym należy wymusić niektóre niezmienniki. łącząc każdą możliwą metodę, która działa na typie z samym typem, TO jest coś, co prowadzi do złożonego i niemożliwego do utrzymania kodu. Zgadzam się z Robertem, możesz spojrzeć na to, jak działają funkcjonalni programiści, może to być naprawdę przyciągające wzrok!Jest tutaj wiele świetnych odpowiedzi i są one o wiele bardziej wnikliwe i oparte na wiedzy niż cokolwiek, co kiedykolwiek mogłem wymyślić jako odpowiedź, ale czuję, że jest coś, o czym nie ma mowy:
„Nasz architekt zdecydował, że stosujemy wszystkie metody statyczne dla wszystkich interfejsów API. Jego rozumowanie jako metody statyczne jest niewielkie i przynosi korzyści aplikacjom internetowym, utrzymując obciążenie serwera ”.
(śmiały nacisk jest mój)
Moje 2c w tej części pytania brzmi:
Teoretycznie to, co jest powiedziane, jest prawdą: wywołanie metody statycznej ma jedynie narzut związany z faktycznym wywołaniem tej metody. Wywołanie metody niestatycznej (instancji) wiąże się z dodatkowym nakładem pracy związanym z pierwszą instancją obiektu, aw pewnym momencie zniszczeniem instancji (ręcznie lub za pomocą jakiejś formy automatycznego wyrzucania elementów bezużytecznych, w zależności od używanej platformy).
Zagraj trochę rzecznika diabła w tym: możemy pójść jeszcze dalej i powiedzieć takie rzeczy jak:
może to stać się naprawdę złe, jeśli instancja jest tworzona dla każdego wywołania metody (instancji) (w przeciwieństwie do pozostawienia jej statycznego i wywołania w ten sposób)
w zależności od złożoności konstruktora, rodzaju herarchii, innych elementów instancji i innych takich nieznanych czynników, dodatkowe obciążenie związane z niestatycznym wywołaniem metody może się różnić i stać się naprawdę duże
Prawdę mówiąc, IMHO, powyższe punkty (i ogólne podejście „używajmy statyki, ponieważ są one szybsze”) są argumentami / ocenami słomianego człowieka:
jeśli kod jest dobry i, bardziej konkretnie dla tego argumentu, jeśli instancje są tworzone tylko wtedy, gdy jest to konieczne (i niszczone w optymalny sposób), wówczas nie ma dodatkowego obciążenia związanego z używaniem metod ubezpieczenia, gdy jest to właściwe (ponieważ jeśli twórz tylko potrzebne obiekty, zostałyby one utworzone, nawet gdyby ta metoda została zadeklarowana jako statyczna, gdzie indziej = narzut ten sam narzut)
przez nadużywanie deklaracji metod statycznych w ten sposób można ukryć pewne problemy z kodem w odniesieniu do sposobu tworzenia instancji (ponieważ metoda jest statyczna, niepoprawny kod instanencji może przejść niezauważony do później, a to nigdy nie jest dobre).
źródło
To bardzo interesujące pytanie, które zazwyczaj ma bardzo różne odpowiedzi w zależności od społeczności, o którą pytasz. Inne odpowiedzi wydają się być stronnicze w języku C # lub java: język programowania, który jest (głównie) czysty obiektowo i ma rodzaj idiomatycznego poglądu na to, czym jest orientacja obiektowa.
W innych społecznościach, takich jak C ++, orientacja obiektowa jest interpretowana z większą swobodą. Niektórzy znani eksperci studiowali ten temat i faktycznie stwierdzili, że wolne funkcje poprawiają enkapsulację (nacisk jest mój):
Dla osób niezaznajomionych z terminologią C ++:
Teraz, aby odpowiedzieć na pytanie:
Nie, nie zawsze należy stosować metody statyczne.
Ale powinieneś ich używać, ilekroć potrzebujesz tylko publicznego interfejsu API klasy.
źródło
w Javie ...
Metody statyczne nie są nadpisywane, ale są ukryte, dlatego duża różnica (problem?) W przypadku rozszerzenia klasy byłaby duża.
Z drugiej strony zauważyłem, że programiści Java mają tendencję do myślenia, że wszystko MUSI BYĆ przedmiotem, nie do końca rozumiejąc dlaczego, i nie zgadzam się.
W przypadku kodu specyficznego dla klasy należy zastosować wartość statyczną. Statyczne nie działa dobrze z dziedziczeniem.
Dobrymi przykładami zastosowania metod statycznych są niezależne funkcje bez skutków ubocznych.
zobacz także słowo kluczowe zsynchronizowane ...
źródło