Почему статический метод считается методом?

135

Я пишу объяснение некоторого кода для курса, и случайно использовал слова methodи functionвзаимозаменяемо. Я решил вернуться и исправить формулировку, но наткнулся на дыру в моем понимании.

Из того, что я понимаю, подпрограмма - это, functionесли она не действует на экземпляр класса (ее эффект ограничен его явным вводом / выводом), и это methodесли она действует на экземпляр класса (она может нести побочные эффекты на случай, который делает его нечистым).

Здесь есть хорошая дискуссия на эту тему. Обратите внимание, что согласно принятым определениям ответа, static methodдолжен фактически быть функцией, потому что экземпляр никогда не передается неявно, и он не имеет доступа ни к каким членам экземпляра.

С этим разум, хотя, разве статика не должна быть на methodsсамом деле функциями?

По их определению они не действуют на конкретные экземпляры класса; они только «привязаны» к классу из-за родства. Я видел несколько хорошо выглядящих сайтов, которые ссылаются на статические подпрограммы как «методы» ( Oracle , Fredosaurus , ProgrammingSimplified ), поэтому либо они все пропускают терминологию, либо я что-то упускаю (я думаю, что последнее) ,

Я хотел бы убедиться, что я использую правильную формулировку.
Кто-нибудь может это прояснить?

Carcigenicate
источник
2
Я всегда думал, что это функция в PHP и метод в Java. В основном одно и то же с разными именами
JK
19
Есть разница между теоретической информатикой и тем, как ее применяет язык. JLS не делает различий и называет это методом.
Джероен Ванневел
2
Это может быть интересно посмотреть на определениях «функции» и «метод» в Python, где есть разница: в основном, функция представляет собой фрагмент кода с таблицей символов и вызывающей конвенцией, в то время как метод , что вы получаете, когда вы помещаете функцию в класс. Разница довольно тонкая, хотя даже для людей, которые знают Python.
Дэвид Z
2
Когда я изучал теорию, я узнал, что функция возвращает значение, а процедура - нет. Затем я изучил функции вызова и методы вызова Java. Сейчас я пробую функциональное программирование, и функция идемпотентна. Термины меняют значение в контексте.
Эмори

Ответы:

123

Эта цитата из 8.4.3.2 может помочь:

Объявленный метод staticназывается методом класса .

Не объявленный методstatic называется методом экземпляра [...].

  • Методы класса: связаны с классом.
  • Методы экземпляра: связаны с экземпляром.

Java просто хочет, чтобы вы «думали об объектно-ориентированном». Кроме того, статические методы имеют доступ к окружающей области, которая может включать в себя состояние. В каком-то смысле класс похож на сам объект.

Radiodef
источник
При этом, хотя «функция» технически правильна как единица выполнения в Java, предпочтительной номенклатурой практически во всей Java является «метод», поскольку все функции Java являются частью класса или интерфейса (за исключением лямбда-выражений и, возможно, некоторые другие вещи, о которых я не знаю).
Дробовик ниндзя
1
Лямбды на самом деле являются анонимными внутренними классами с @FunctionalInterfaceаннотацией и одним методом. Лямбда - это просто синтаксический сахар, и в этом нет ничего нового.
Адам Арольд
1
@AdamArold Lambdas - немного более изящный, чем анонимный внутренний класс. Например, лямбды без захвата могут совместно использовать экземпляр в нескольких оценках определенного выражения. (Но вы правы, они в конечном итоге компилируются в статические методы и методы экземпляров.)
Radiodef
@Radiodef Возможно, лучший способ выразить это словами: «Все лямбда-выражения можно заменить эквивалентными не лямбда-выражениями, не внося никаких изменений в файлы, отличные от того, который содержит лямбда-выражение» или что-то в этом роде.
user253751
4
Я смущен. Я из Скалы, и все же мне удалось пропустить тот факт, что сам класс подобен объекту. Спасибо.
Carcigenicate
80

Простой ответ заключается в том, что когда Java решила назвать все «методом», они не заботились о разнице между функцией и методом в теоретической информатике.

Биткойн М
источник
3
Это правильно. До и включая Java 7 вы даже не найдете слово «функция» в Спецификации языка
Эрвин Болвидт
4
Как бы мне ни нравилась простота этого ответа, я думаю, что ответ Radiodef более актуален, поскольку в нем упоминается ключевой момент, согласно которому сам класс действует как объект. Однако, спасибо.
Carcigenicate
2
Интересно, что это происходит параллельно с решениями более ранних языков не проводить различий между функциями и подпрограммами.
Random832,
4
Я неприятно удивлен, что этот ответ получил так много голосов. Во-первых, этот ответ делает вид, что методы класса не существуют. Во-вторых, это вряд ли концепция, представленная в Java. Например, методы класса уже существовали в Smalltalk, который существовал в течение десятилетий, прежде чем Java стала чем-то особенным.
Малкольм
1
@ Малкольм, я должен с тобой согласиться. После рассмотрения других ответов это кажется неправильным. Это не апатия со стороны создателя Java, если только они действительно не заботятся, но в итоге назвали его правильно, несмотря ни на что.
Карцигеникат
26

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

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

Но статические методы могут обращаться к статическим переменным и другим статическим функциям (также используя статические переменные), поэтому статические методы могут иметь состояние, которое принципиально отличается от функции, которая по определению не имеет состояния . (ДОБАВЛЕНИЕ: Хотя программисты часто не так строги в использовании «функции» как определения, строгая функция в информатике может получить доступ только к входным параметрам). Поэтому, определяя этот случай доступа к статическим полям, нельзя утверждать, что статические методы всегда являются функциями.

Другое отличие, которое оправдывает использование «статического метода», состоит в том, что вы можете определить в C производные глобальных функций и глобальные переменные, к которым можно получить доступ везде. Если вы не можете получить доступ к классу, который содержит статические методы, методы также недоступны. Таким образом, «статические методы» ограничены в своей области дизайна в отличие от глобальных функций.

Торстен С.
источник
2
Мне нравится этот ответ, но я хотел бы лучше понять некоторые вещи. Разве это не скорее «чистая» против «побочной» функции, нежели функция против метода? Или метод такой из-за побочных эффектов? Я просто мозговой штурм здесь.
Надир Сампаоли
2
Этот ответ правильный. Однако можно утверждать, что функции во многих (большинстве?) Языках могут иметь доступ к глобальным переменным, поэтому они часто не являются строго не имеющими состояния (один и тот же ввод, один и тот же вывод). А в случае статических методов Java доступ к переменным класса может считаться эквивалентным доступу к «глобальным» (то есть не локальным к функции / методу) переменным - при этом экземпляр класса является своего рода пространством имен.
leonbloy
1
@leonbloy Pure Функциональные языки программирования, такие как Haskell, полностью не сохраняют состояния; нет ничего, что можно назвать глобальной переменной.
Торстен С.
17

В Java пользовательский класс на самом деле является экземпляром подкласса java.lang.Class.

В этом смысле, статические методы будут прикреплены к экземпляру концептуального класса: они прикрепляются к экземпляру подкласса java.lang.Class.

Имея это в виду, термин «метод класса» (альтернативное имя для статических методов Java) начинает иметь смысл. И термин «метод класса» можно найти во многих местах: Objective C, Smalltalk и JLS - это лишь некоторые из них.

Майк Кларк
источник
Возможно ли иметь два экземпляра этого подкласса?
Random832
Конечно, вы можете загрузить класс в разные загрузчики классов (причина получения исключений ClassCastException с сообщением «невозможно преобразовать CustomClass в CustomClass»).
Данни
2
@ Random832 - вроде. Вы можете иметь два (или более) экземпляра одного и того же подкласса Class в одной и той же JVM, если каждый экземпляр имеет свой отдельный загрузчик классов. Вы не можете создавать один и тот же подкласс класса более одного раза для каждого загрузчика классов. Это немного сбивает с толку, и на этом этапе аналогии с классическими концепциями ОО начинают немного растягиваться.
Майк Кларк
@MikeClark, если я это сделаю, они действительно одинаковы? Например, будет ли подкласс Class одним и тем же классом, даже если сам класс является другим его экземпляром? Загрузчики классов меня довольно смущают. Могу ли я вызвать (без отражения) статический метод экземпляра одного загрузчика классов из другого экземпляра загрузчика классов того же класса, передав ссылку на него? Что если у них разные методы?
Random832
1
@ Random832 "Вроде?" С чисто теоретической точки зрения, действительно ли два экземпляра класса действительно одинаковы? По крайней мере два идентичных экземпляра одного и того же класса будут иметь разные адреса. Иначе, как мы можем иметь две вещи? Единственное, что в точности совпадает с чем-то, это сама вещь.
Майк Кларк
11

В информатике функция четко отображается на статический метод. Но «метод» класса является немного общим, как «член» (член поля, член метода). Есть такие формулировки, как

Элементы данных и члены метода имеют два отдельных пространства имен: .x и .x () могут сосуществовать.

Таким образом, причина в том, что, как сказал философ Людвиг Витгенштейн, язык - это инструмент в разных контекстах. «Метод» - это хорошее прозвище в приведенной выше цитате для классификации «члена».

Joop Eggen
источник
9

Ваше мышление правильно, и это имеет смысл. Это просто не установленная терминология в сообществе Java. Позвольте мне объяснить некоторые внутренние принципы, которые могут помочь понять, почему терминология существует.

Java - это объектно-ориентированный язык на основе классов. Метод всегда является членом класса или экземпляра (это общее утверждение, допустимое и для других языков программирования). Мы думаем, что класс и экземпляр - оба объекта.

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

Вы не можете вызвать этот метод непосредственно из класса, вам нужно создать экземпляр. Каждый экземпляр ссылается на этот метод. Вы можете переписать определение метода с точно такой же сигнатурой метода (при создании подкласса), то есть ссылка указывает на другой метод (который имеет ту же сигнатуру, но может иметь другое тело метода). Метод динамический.

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

Вы можете напрямую вызвать этот метод только из класса, т.е. вам не нужно создавать экземпляр этого класса. Существует только одно глобальное определение этого метода во всей программе. Вы не можете перезаписать точно такую ​​же сигнатуру метода, когда метод объявлен как статический, потому что существует только одно определение, действительное для всей программы. Обратите внимание, что метод является членом самого объекта класса, экземпляры имеют одинаковую уникальную (и фиксированную) ссылку на этот метод.

Ely
источник
7

Вот еще один подход к терминологии, использующий Scala в качестве мнемоники:
в Scala у вас есть objects, которые являются единичными экземплярами неявно определенного класса1 .

По вашему определению мы можем вызывать эти подпрограммы, принадлежащие object методам , так как они работают с одним экземпляром класса.
Кроме того, объект также определит класс A и создаст все методы в объекте A как статические методы в классе A (для взаимодействия с Java) [2] .

Поэтому мы можем сказать, что статические методы Java-класса A имеют доступ к тем же членам, что и одноэлементный экземпляр Scala, которые по вашему определению заслуживают того, чтобы называться (статическими) методами класса A.

mucaho
источник
Отличное сравнение. Я знаю Scala, так что ваша objectссылка имеет большой смысл. Спасибо.
Carcigenicate
2

Конечно, основное отличие заключается в том, что метод может использовать статические поля, а не только параметры метода. Но есть еще один - полиморфизм! Результаты оценки Класс A.doTheSameStaticMethod () и ClassB.doTheSameStaticMehod () будут зависеть от класса. В этом случае функция бессильна.

Павел Бивойно
источник
1

Каждый класс имеет объект для его представления, который является экземпляром подкласса Classкласса. Статические методы - это действительно методы экземпляров этих объектов, которые являются экземплярами подкласса Class. У них есть доступ к состоянию в виде статических полей, поэтому они не ограничиваются только функциями (без сохранения состояния). Это методы.

Богемский
источник