Чому статичний метод вважається методом?


135

Я пишу пояснення щодо коду для курсу і випадково використовую слова methodта functionвзаємозамінно. Я вирішив повернутися назад і виправити формулювання, але наткнувся на дірку в своєму розумінні.

З того, що я розумію, підпрограма - це, functionякщо вона не діє на екземпляр класу (її ефект обмежується явним входом / виходом), і є, methodякщо вона працює над екземпляром класу (може мати виключати побічні ефекти для екземпляра, які роблять його нечистим)

Тут добре обговорюється тема. Зауважте, що за визначеннями прийнятої відповіді статика methodнасправді повинна бути функцією, оскільки екземпляр ніколи не передається неявно, і він не має доступу до членів будь-якого інстанції.

Однак, маючи це на увазі, чи не повинні статичні methodsфактично бути функціями?

За їх визначенням вони не діють на конкретні екземпляри класу; вони лише "прив'язані" до класу через відношення. Я бачив декілька гарних веб-сайтів, які посилаються на статичні підпрограми як "методи" ( Oracle , Fredosaurus , ProgrammingSimplified ), тому або всі вони оглядають термінологію, або мені щось не вистачає (я здогадуюсь останнього) .

Я хотів би переконатися, що я використовую правильне формулювання.
Хтось може це очистити?


2
Я завжди думав, що це функція в php та методі на Java. В основному те саме з різними іменами
JK

19
Існує різниця між теоретичною інформатикою та тим, як мова застосовує її. JLS не робить відмінностей і називає це методом.
Єроен Ванневель


2
Можливо, буде цікаво ознайомитись з визначеннями "функції" та "методу" в Python, де є різниця: в основному, функція - це фрагмент коду з таблицею символів та умовою виклику, тоді як метод - це те, що ви отримуєте, коли кладете функцію в клас. Однак різниця досить тонка, навіть людям, які знають Python.
David Z

2
Коли я вивчав теорію, я дізнався, що функція повертає значення, а процедура - ні. Потім я навчився методам викликів Java і методів процедур. Тепер я пробую функціональне programmjng, і функція безсильна. Терміни змінюють значення в контексті.
Еморі

Відповіді:


123

Ця цитата з 8.4.3.2 може допомогти:

Метод, який оголошується static, називається методом класу .

Метод, який не оголошується static, називається методом екземпляра [...].

  • Методи класу: пов'язані з класом.
  • Методи екземпляра: пов'язані з екземпляром.

Java просто хоче, щоб ви "думали, що орієнтовані на об'єкти". Також статичні методи мають доступ до оточуючої області, яка може включати стан. Певним чином клас схожий на сам об’єкт.


Це означає, що "функція" технічно правильна як одиниця виконання на Java, номенклатура, що вподобається, у всій Java є "методом", оскільки всі функції Java є частиною класу або інтерфейсу (за винятком лямбда, і можливо деякі інші речі, про які я не знаю).
Стрілецький ніндзя

1
Лямбди - це фактично анонімні внутрішні класи з @FunctionalInterfaceанотацією та з 1 методом під кришкою. Лямбда - це просто синтаксичний цукор, і в цьому плані немає нічого нового.
Адам Арольд

1
@AdamArold Ламбдас є трохи більш фантазійним, ніж анонімний внутрішній клас. Наприклад, лямбди, що не захоплюють, можуть поділяти екземпляр у кількох оцінках певного виразу. (Але ви маєте рацію, вони в кінцевому підсумку збираються до статичних та екземплярних методів.)
Radiodef

@Radiodef Може бути кращим способом висловити це слово "Всі лямбда-вирази можна замінити на еквівалентні не лямбда-вирази, не вносячи жодних змін у файли, окрім того, що містять лямбда-вираз" або щось подібне.
користувач253751

4
Мені соромно. Я родом із Scala і все-таки вдалося пропустити той факт, що сам клас є об’єктоподібним. Дякую.
Carcigenicate

80

Проста відповідь полягає в тому, що коли Java вирішила назвати все "методом", вони не переймалися різницею між функцією та методом в теоретичній інформатиці.


3
Це вірно. До включення Java 7 ви навіть не знайдете слово "функція" у специфікації мови
Ервін Болвідт

4
Наскільки мені подобається простота цієї відповіді, я вважаю, що відповідь Radiodef більше відповідає, оскільки в ній згадується ключовий момент, що сам клас виступає в якості об'єкта. Дякую, хоча.
Carcigenicate

2
Цікаво, що це паралельно з рішеннями попередніх мов не розрізняти функції та підпрограми.
Випадково832

4
Я неприємно здивований, що ця відповідь отримала так багато відгуків. По-перше, ця відповідь робить вигляд, що методи класу не існують. По-друге, це навряд чи концепція, запроваджена на Java. Класові методи вже існували в Smalltalk, наприклад, який існував десятиліттями до того, як Java стала річчю.
Малькольм

1
@Malcolm Я повинен з тобою погодитися. Після розгляду інших відповідей це здається неправильним. Це не апатія з боку творця Java, якщо тільки вони по-справжньому не хвилювались, але в кінцевому підсумку називали її правильно.
Carcigenicate

26

Статичні методи - це не зовсім функції, різниця тонка, але важлива.

Статичний метод, що використовує лише задані вхідні параметри , по суті є функцією.

Але статичні методи можуть отримувати доступ до статичних змінних та інших статичних функцій (також використовуючи статичні змінні), тому статичні методи можуть мати стан, який принципово відрізняється від функції, яка за визначенням є без громадянства . (ДОБАВЛЕННЯ: Хоча програмісти часто не такі суворі з використанням "функції", як визначення, сувора функція в галузі інформатики може отримати доступ лише до вхідних параметрів). Отже, визначаючи цей випадок доступу до статичних полів, невірно сказати, що статичні методи - це завжди функції.

Ще одна відмінність, яка виправдовує використання "статичного методу", полягає в тому, що ви можете визначити в C похідних глобальні функції та глобальні змінні, до яких можна отримати доступ всюди. Якщо ви не можете отримати доступ до класу, що містить статичні методи, методи також недоступні. Тож "статичні методи" обмежені за своєю сферою застосування дизайном на відміну від глобальних функцій.


2
Мені подобається ця відповідь, але я хотів би краще зрозуміти деякі речі. Хіба це не більше функція "чистий" проти "побічних ефектів", а не метод проти функції? Або це метод такий через побічні ефекти? Я тут просто мозковий штурм.
Надір Сампаоолі

2
Ця відповідь правильна. Однак можна стверджувати, що функції багатьох (більшості?) Мов можуть отримати доступ до глобальних змінних, тому вони часто не є суто бездержавними (той самий вхід, той самий вихід). А у випадку статичних методів Java, доступ до змінних класів можна вважати еквівалентним до доступу до "глобальних" (тобто не локальних для функції / методу) змінних - при цьому екземпляр класу є своєрідним простором імен.
leonbloy

1
@leonbloy Чисті функціональні мови програмування, такі як Haskell, абсолютно без громадянства; немає нічого, що можна назвати глобальною змінною.
Торстен С.

17

У Java визначений користувачем клас - це фактично екземпляр підкласу java.lang.Class.

У цьому сенсі, статичні методи будуть прикріплені до примірника концептуального класу: вони прикріплюються до примірника підкласу java.lang.Class.

Зважаючи на це, термін «метод класу» (альтернативна назва статичних методів Java) починає мати сенс. А термін "метод класу" можна зустріти у багатьох місцях: ціль C, Smalltalk та JLS - щоб назвати лише кілька.


Чи можливо мати два екземпляри цього підкласу?
Випадково832

Звичайно, ви можете завантажити клас у різних завантажувачів класів (причина отримання ClassCastExceptions з повідомленням "не може передавати CustomClass в CustomClass").
dunni

2
@ Random832 - начебто. Ви можете мати два (або більше) екземплярів одного підкласу Class в одному JVM, якщо кожен екземпляр має свій окремий завантажувач класів. Ви не можете створювати один і той же підклас класу більше одного разу на кожного завантажувача класів. Це стає трохи заплутаним, і аналогії з класичними концепціями OO починають трохи розтягуватися в цій точці.
Майк Кларк

@MikeClark, якщо я це роблю, чи справді вони однакові? Мовляв, чи буде підклас Class одного класу, навіть якщо сам клас є його іншим примірником? Навантажувачі мене дуже бентежать. Чи можу я зателефонувати (без відображення) статичним методом одного екземпляра завантажувача класу з іншої інстанції того ж класу завантажувача, маючи посилання на нього, передане в ньому? Що робити, якщо у них різні методи?
Випадково832

1
@ Random832 "Сортувати?" З чисто ГО теорії точки зору, будь-які два примірника класу ніколи дійсно точно так же? Як мінімум, два ідентичні екземпляри одного класу матимуть різні адреси. Інакше, як ми можемо мати дві речі? Єдине, що точно таке, як щось, - це сама річ.
Майк Кларк

11

У інформатиці функція чітко відображається до статичного методу. Але "метод" класу дещо загальний, як "член" (член поля, член методу). Є такі фрази, як

У членів даних та членів методу є два окремих простору імен: .x та .x () можуть співіснувати.

Отже, причина полягає в тому, що, як сказав філософ Людвіг Вітгенштейн, Мова - це інструмент з різними контекстами. "Метод" - це приємний посібник у наведеному вище цитуванні для категоризації "члена".


9

Ваше мислення правильне і має сенс. Це просто не встановлена ​​термінологія в спільноті Java. Дозвольте пояснити деякі внутрішні відомості, які можуть допомогти зрозуміти, чому термінологія існує.

Java - об'єктно-орієнтована мова на основі класу. Метод завжди є членом класу або екземпляра (Це загальне твердження, що діє і для інших мов програмування). Ми думаємо, що клас і екземпляр є обома об'єктами.

Метод екземпляра (динамічний)

Ви не можете викликати цей метод безпосередньо з класу, ви повинні створити екземпляр. Кожен екземпляр посилається на цей метод. Ви можете замінити визначення методу точно таким же підписом методу (підкласифікація), тобто опорними точками на інший метод (який має ту саму підпис, але може мати інше тіло методу). Метод динамічний.

Метод класу (статичний)

Ви можете лише посилатися на цей метод із класу безпосередньо, тобто вам не потрібно створювати примірник цього класу. У всій програмі існує лише одне глобальне визначення цього методу. Ви не можете перезаписати той самий підпис методу, коли метод оголошений статичним, оскільки існує лише одне визначення, дійсне для всієї програми. Зауважте, що метод є членом самого об’єкта класу, екземпляри мають однакові (і виправлені) посилання на цей метод.


7

Ось ще один взяття на термінологію, використовуючи Scala як мнемонічний:
У Scala у вас є objects, які є однотонними екземплярами неявно визначеного класу1 .

Згідно з вашим визначенням, ми можемо назвати ці підпрограми, що належать до object методів , оскільки вони працюють на одному екземплярі класу.
Крім того, об’єкт також визначатиме клас A і створює всі методи в об'єкті A як статичні методи класу A (для взаємодії з Java) [2] .

Тому ми можемо сказати, що статичні методи класу Java Java мають доступ до тих самих членів, що й екземпляр Scala Singleton, які відповідно до вашого визначення заслуговують називатися (статичними) методами класу A.


Чудове порівняння. Я знаю Scala, тому ваша objectдовідка має багато сенсу. Дякую.
Carcigenicate

2

Звичайно, головна відмінність - метод може використовувати статичні поля, а не лише параметри методу. Але є ще один - поліморфізм! Результати оцінювання Клас A.doTheSameStaticMethod () та ClassB.doTheSameStaticMehod () буде залежати від класу. У цьому випадку функція безсильна.


1

Кожен клас має об'єкт для його представлення, який є примірником підкласу Classкласу. Статичні методи - це дійсні екземплярні методи на цих об'єктах, які є примірниками підкласу Class. Вони мають доступ до стану у вигляді статичних полів, тому вони не обмежуються лише функціями (без стану). Вони є методами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.