Dlaczego metoda statyczna jest uważana za metodę?

135

Piszę wyjaśnienie dla jakiegoś kodu kursu i przypadkowo używam słów methodi functionzamiennie. Postanowiłem wrócić i poprawić sformułowanie, ale wpadłem w lukę w moim zrozumieniu.

Z tego, co rozumiem, podprogram jest a, functionjeśli nie działa na instancję klasy (jej efekt jest ograniczony do jej jawnego wejścia / wyjścia) i jest a, methodjeśli działa na instancji klasy (może przenosić skutki uboczne instancji, które czynią ją nieczystą).

Jest tutaj dobra dyskusja na ten temat. Zauważ, że zgodnie z przyjętymi definicjami odpowiedzi statyczna methodpowinna w rzeczywistości być funkcją, ponieważ instancja nigdy nie jest niejawnie przekazywana i nie ma dostępu do elementów członkowskich żadnej instancji.

Mając to na uwadze, czy statyczne nie powinny methodsbyć w rzeczywistości funkcjami?

Z definicji nie działają na określonych instancjach klasy; są „przywiązani” do klasy tylko ze względu na pokrewieństwo. Widziałem kilka dobrze wyglądających witryn, które odnoszą się do statycznych podprogramów jako „metod” ( Oracle , Fredosaurus , ProgrammingSimplified ), więc albo wszystkie przeoczają terminologię, albo czegoś mi brakuje (przypuszczam, że to drugie) .

Chciałbym się upewnić, że używam właściwego sformułowania.
Czy ktoś może to wyjaśnić?

Carcigenicate
źródło
2
Zawsze myślałem, że to funkcja w PHP i metoda w Javie. Zasadniczo to samo z różnymi nazwami
JK
19
Istnieje różnica między informatyką teoretyczną a tym, jak język ją stosuje. JLS nie rozróżnia i nazywa to metodą.
Jeroen Vannevel
2
To może być interesujące spojrzenie na definicji „funkcji” i „metody” w Pythonie, gdzie jest różnica: w zasadzie, to funkcja jest fragment kodu z tablicy symboli i konwencji wywołania, podczas gdy metoda jest co otrzymasz, gdy umieścisz funkcję w klasie. Różnica jest jednak dość subtelna, nawet dla osób znających Python.
David Z
2
Kiedy uczyłem się teorii, nauczyłem się, że funkcja zwraca wartość, a procedura nie. Potem nauczyłem się wywołań java, metod i procedur. Teraz próbuję programowanie funkcjonalne i funkcja jest idempotentna. Terminy zmieniają znaczenie w kontekście.
emory

Odpowiedzi:

123

Ten cytat z 8.4.3.2 może pomóc:

Zadeklarowana metodastatic nazywana jest metodą klasy .

Metoda, która nie została zadeklarowana, staticnazywana jest metodą instancji [...].

  • Metody klasowe: związane z klasą.
  • Metody instancji: powiązane z instancją.

Java chce tylko, abyś „myślał obiektowo”. Ponadto metody statyczne mają dostęp do otaczającego zakresu, który może obejmować stan. W pewnym sensie klasa jest jak sam obiekt.

Radiodef
źródło
To powiedziawszy, chociaż „funkcja” jest technicznie poprawna jako jednostka wykonania w Javie, preferowaną nomenklaturą w prawie całej Javie jest „metoda”, ponieważ wszystkie funkcje Java są częścią klasy lub interfejsu (z wyłączeniem lambd i być może inne rzeczy, których nie jestem świadomy).
Shotgun Ninja
1
Lambdy są w rzeczywistości anonimowymi klasami wewnętrznymi z @FunctionalInterfaceadnotacją i jedną metodą pod maską. Lambda to po prostu cukier syntaktyczny i pod tym względem nie ma nic nowego.
Adam Arold
1
@AdamArold Lambdy są nieco bardziej wyszukane niż anonimowa klasa wewnętrzna. Na przykład wyrażenia lambda nieprzechwytywane mogą współużytkować wystąpienie w wielu ocenach określonego wyrażenia. (Ale masz rację, ostatecznie skompilowano je do metod statycznych i instancji.)
Radiodef,
@Radiodef Być może lepszym sposobem wyrażenia tego byłoby „Wszystkie wyrażenia lambda można zastąpić równoważnymi wyrażeniami innymi niż lambda, bez dokonywania jakichkolwiek zmian w plikach innych niż ten zawierający wyrażenie lambda” lub coś w tym rodzaju.
user253751
4
Jestem zażenowany. Pochodzę ze Scali i wciąż udało mi się przeoczyć fakt, że sama klasa jest obiektowa. Dziękuję Ci.
Carcigenicate
80

Prosta odpowiedź jest taka, że ​​kiedy Java zdecydowała się nazywać wszystko „metodą”, nie obchodziło ich rozróżnienie między funkcją a metodą w informatyce teoretycznej.

Bitcoin M.
źródło
3
Zgadza się. Do czasu włączenia Java 7 nie znajdziesz nawet słowa „funkcja” w specyfikacji języka
Erwin Bolwidt
4
Chociaż podoba mi się prostota tej odpowiedzi, myślę, że odpowiedź Radiodefa jest bardziej na dobrej drodze, ponieważ wspomina o kluczowym punkcie, że sama klasa działa jako obiekt. Ale dziękuję.
Carcigenicate
2
Co ciekawe, jest to równoległe z decyzjami wcześniejszych języków, aby nie rozróżniać funkcji i podprogramów.
Random832
4
Jestem niemile zaskoczony, że ta odpowiedź spotkała się z tak wieloma pozytywnymi opiniami. Po pierwsze, ta odpowiedź udaje, że metody klasowe nie istnieją. Po drugie, nie jest to koncepcja wprowadzona w Javie. Na przykład metody klasowe istniały już w Smalltalk, który istniał przez dziesięciolecia, zanim Java stała się popularna.
Malcolm
1
@Malcolm Muszę się z tobą zgodzić. Po rozważeniu innych odpowiedzi wydaje się to błędne. To nie jest apatia ze strony twórców Javy, chyba że naprawdę ich to nie obchodziło, ale mimo to nazwali go poprawnie.
Carcigenicate
26

Metody statyczne nie są dokładnie funkcjami, różnica jest subtelna, ale ważna.

Metoda statyczna wykorzystująca tylko podane parametry wejściowe jest zasadniczo funkcją.

Jednak metody statyczne mogą uzyskiwać dostęp do zmiennych statycznych i innych funkcji statycznych (również wykorzystujących zmienne statyczne), więc metody statyczne mogą mieć stan zasadniczo różny od funkcji, które z definicji są bezstanowe . (DODATEK: Podczas gdy programiści często nie są tak restrykcyjni w używaniu „funkcji” jako definicji, ścisła funkcja w informatyce może mieć dostęp tylko do parametrów wejściowych). Zatem definiując ten przypadek dostępu do pól statycznych, nie można powiedzieć, że metody statyczne są zawsze funkcjami.

Inną różnicą, która uzasadnia użycie „metody statycznej”, jest to, że w C derywuje funkcje globalne i zmienne globalne, do których można uzyskać dostęp wszędzie. Jeśli nie możesz uzyskać dostępu do klasy, która zawiera metody statyczne, metody te również są niedostępne. Tak więc „metody statyczne” mają ograniczony zakres ze względu na projekt w przeciwieństwie do funkcji globalnych.

Thorsten S.
źródło
2
Podoba mi się ta odpowiedź, ale chciałbym lepiej zrozumieć kilka rzeczy. Czy nie jest to bardziej funkcja „czysta” kontra „efekt uboczny”, a nie funkcja kontra metoda? A może metoda jest taka z powodu skutków ubocznych? Robię tu tylko burzę mózgów.
Nadir Sampaoli
2
Ta odpowiedź jest prawidłowa. Można jednak argumentować, że funkcje w wielu (większości?) Językach mają dostęp do zmiennych globalnych, więc często nie są one całkowicie bezstanowe (to samo wejście, to samo wyjście). W przypadku metod statycznych Java dostęp do zmiennych klas można uznać za równoważny z dostępem do zmiennych „globalnych” (tj. Nie lokalnych dla funkcji / metody) - przy czym instancja klasy jest rodzajem przestrzeni nazw.
leonbloy
1
@leonbloy Czyste funkcjonalne języki programowania, takie jak Haskell, są całkowicie bezstanowe; nie ma nic, co można nazwać zmienną globalną.
Thorsten S.
17

W Javie klasa zdefiniowana przez użytkownika jest w rzeczywistości instancją podklasy java.lang.Class.

W tym sensie metody statyczne dołączane do instancji klasy pojęciowej: są dołączane do instancji podklasy java.lang.Class.

Mając to na uwadze, termin „metoda klasowa” (alternatywna nazwa metod statycznych Javy) zaczyna mieć sens. A termin „metoda klasowa” można znaleźć w wielu miejscach: Objective C, Smalltalk i JLS - żeby wymienić tylko kilka.

Mike Clark
źródło
Czy można mieć dwie instancje tej podklasy?
Random832
Oczywiście możesz załadować klasę do różnych klas ładujących (przyczyna pobierania wyjątków ClassCastExceptions z komunikatem „nie można rzutować klasy CustomClass na CustomClass”).
dunni
2
@ Random832 - w pewnym sensie. W tej samej maszynie JVM można mieć dwie (lub więcej) instancji tej samej podklasy Class, o ile każda instancja ma własny, oddzielny moduł ładujący klasy. Nie można utworzyć wystąpienia tej samej podklasy Class więcej niż raz na program ładujący klasy. Robi się to trochę zagmatwane i analogie do klasycznych koncepcji OO zaczynają się nieco rozciągać w tym momencie.
Mike Clark
@MikeClark, jeśli to zrobię, czy naprawdę są takie same? Na przykład, czy podklasa Class będzie tą samą klasą, nawet jeśli sama klasa jest inną jej instancją? Classloadery są dla mnie dość zagmatwane. Czy mogę wywołać (bez odbicia) statyczną metodę jednej instancji klasy modułu ładującego z innej instancji tej samej klasy, poprzez przekazanie do niej odwołania? A jeśli mają inne metody?
Random832
1
@ Random832 "W pewnym sensie?" Czy z czysto teoretycznego punktu widzenia jakieś dwa wystąpienia klasy są naprawdę takie same? Co najmniej dwie w inny sposób identyczne instancje tej samej klasy będą miały różne adresy. W przeciwnym razie, jak możemy mieć dwie rzeczy? Jedyną rzeczą, która jest dokładnie tym samym, co coś, jest sama rzecz.
Mike Clark
11

W informatyce funkcja wyraźnie odwzorowuje metodę statyczną. Ale „metoda” klasy jest nieco ogólna, jak „element członkowski” (element członkowski pola, element członkowski metody). Istnieją sformułowania takie jak

Składowe danych i elementy składowe metod mają dwie oddzielne przestrzenie nazw: .x i .x () mogą współistnieć.

A więc powód jest taki, że, jak powiedział filozof Ludwig Wittgenstein, język jest narzędziem o różnych kontekstach. „Metoda” to fajny pseudonim w powyższym cytacie, służący do kategoryzacji „członka”.

Joop Eggen
źródło
9

Twoje myślenie jest właściwe i ma sens. Nie jest to po prostu ustalona terminologia w społeczności Java. Pozwólcie, że wyjaśnię niektóre wewnętrzne elementy, które mogą pomóc zrozumieć, dlaczego terminologia istnieje.

Java to język obiektowy oparty na klasach. Metoda jest zawsze członkiem klasy lub instancji (jest to ogólna instrukcja poprawna również dla innych języków programowania). Myślimy, że klasa i instancja są obiektami.

Metoda instancji (dynamiczna)

Nie możesz wywołać tej metody bezpośrednio z klasy, musisz utworzyć instancję. Każda instancja odwołuje się do tej metody. Definicję metody można nadpisać dokładnie tą samą sygnaturą metody (podczas tworzenia podklas), tj. Odwołanie wskazuje na inną metodę (która ma ten sam podpis, ale może mieć inną treść metody). Metoda jest dynamiczna.

Metoda klasowa (statyczna)

Możesz wywołać tę metodę tylko bezpośrednio z klasy, tj. Nie musisz tworzyć instancji tej klasy. W całym programie istnieje tylko jedna globalna definicja tej metody. Nie można nadpisać dokładnie tej samej sygnatury metody, gdy metoda jest zadeklarowana jako statyczna, ponieważ istnieje tylko jedna definicja ważna dla całego programu. Zwróć uwagę, że metoda jest składową samego obiektu klasy, a wszystkie instancje mają takie same unikalne (i poprawione) odwołania do tej metody.

Ely
źródło
7

Oto inne podejście do terminologii, używając Scali jako mnemonika:
W Scali masz objects, które są pojedynczymi instancjami niejawnie zdefiniowanej klasy1 .

Zgodnie z twoją definicją możemy wywołać te podprogramy należące do object metod , ponieważ działają one na pojedynczym wystąpieniu klasy.
Dodatkowo obiekt zdefiniuje również klasę A i utworzy wszystkie metody w obiekcie A jako metody statyczne w klasie A (do współpracy z Javą) [2] .

Dlatego możemy powiedzieć, że statyczne metody klasy A w Javie mają dostęp do tych samych elementów członkowskich, co instancja pojedyncza Scala, która zgodnie z twoją definicją zasługuje na miano (statycznych) metod klasy A.

mucaho
źródło
Świetne porównanie. Znam Scalę, więc twoje objectodniesienie ma dużo sensu. Dziękuję Ci.
Carcigenicate
2

Oczywiście główna różnica polega na tym, że metoda może wykorzystywać pola statyczne, a nie tylko parametry metody. Ale jest jeszcze jeden - polimorfizm! Wyniki oceny Class A.doTheSameStaticMethod () i ClassB.doTheSameStaticMehod () będą zależne od klasy. W tym przypadku funkcja jest bezsilna.

Павел Бивойно
źródło
1

Każda klasa ma reprezentujący ją obiekt, który jest instancją podklasy tej Classklasy. Metody statyczne są w rzeczywistości metodami instancji tych obiektów, które są instancjami podklasy Class. Mają dostęp do stanu w postaci pól statycznych, więc nie są ograniczone tylko do funkcji (bezstanowych). To są metody.

Czeski
źródło