¿Por qué un método estático se considera un método?

135

Estoy escribiendo una explicación de algún código para un curso, y he estado usando las palabras accidentalmente methode functionindistintamente. Decidí volver y arreglar la redacción, pero me encontré con un agujero.

Por lo que entiendo, una subrutina es functionsi no actúa en una instancia de una clase (su efecto está restringido a su entrada / salida explícita), y es methodsi opera en una instancia de una clase (puede llevar fuera de los efectos secundarios en la instancia que lo hacen impuro).

Aquí hay una buena discusión sobre el tema. Tenga en cuenta que, según las definiciones de la respuesta aceptada, una estática methoddebería ser una función porque una instancia nunca se pasa implícitamente y no tiene acceso a los miembros de ninguna instancia.

Con esto en mente, ¿no debería ser estática methodsrealmente funciones?

Por su definición, no actúan en instancias particulares de una clase; solo están "atados" a la clase debido a su relación. Sin embargo , he visto algunos sitios atractivos que se refieren a las subrutinas estáticas como "métodos" ( Oracle , Fredosaurus , ProgrammingSimplified ), por lo que o todos pasan por alto la terminología o me falta algo (supongo que es lo último) .

Me gustaría asegurarme de que estoy usando la redacción correcta.
¿Alguien puede aclarar esto?

Carcigenicate
fuente
2
Siempre pensé que era función en php y método en Java. Básicamente lo mismo con nombres diferentes
JK
19
Hay una diferencia entre la informática teórica y la forma en que un lenguaje la aplica. El JLS no hace distinción y lo llama un método.
Jeroen Vannevel
2
Podría ser de interés para ver las definiciones de "función" y "método" en Python, donde no es una diferencia: básicamente, una función es un trozo de código con una tabla de símbolos y una convención de llamada, mientras que un método es lo obtienes cuando pones una función en una clase. Sin embargo, la diferencia es bastante sutil, incluso para las personas que conocen Python.
David Z
2
Cuando estaba aprendiendo teoría, aprendí que la función devuelve un valor y el procedimiento no. Entonces aprendí que Java llama funciones y métodos de procedimientos. Ahora estoy intentando programar funcionalmente y una función es idempotente. Los términos cambian de significado en el contexto.
emory

Respuestas:

123

Esta cita de 8.4.3.2 puede ayudar:

Un método que se declara staticse llama método de clase .

Un método que no se declara staticse llama método de instancia [...].

  • Métodos de clase: asociados con una clase.
  • Métodos de instancia: asociados con una instancia.

Java solo quiere que "pienses orientado a objetos". Además, los métodos estáticos tienen acceso a un alcance circundante que puede incluir el estado. En cierto modo, la clase es como un objeto en sí mismo.

Radiodef
fuente
Dicho esto, mientras que "función" es técnicamente correcta como unidad de ejecución en Java, la nomenclatura preferida en casi todo Java es "método", ya que todas las funciones de Java son parte de una clase o interfaz (excluyendo lambdas, y tal vez algunas otras cosas que no conozco).
Shotgun Ninja
1
Las lambdas son en realidad clases internas anónimas con la @FunctionalInterfaceanotación y con 1 método bajo el capó. Una lambda es simplemente azúcar sintáctica y, en ese sentido, no hay nada nuevo.
Adam Arold
1
@AdamArold Lambdas son bastante más elegantes que una clase interna anónima. Por ejemplo, las lambdas que no capturan pueden compartir una instancia en múltiples evaluaciones de una expresión particular. (Pero tienes razón que en última instancia se compilan a métodos estáticos y de instancia.)
Radiodef
@Radiodef Quizás una mejor manera de expresarlo sería "Todas las expresiones lambda pueden reemplazarse por expresiones equivalentes que no sean lambda, sin hacer ningún cambio en los archivos que no sean el que contiene la expresión lambda" o algo así.
user253751
44
Me da vergüenza. Vengo de Scala y todavía me las arreglé para perder el hecho de que la clase en sí misma es como un objeto. Gracias.
Carcigenicate
80

La respuesta simple es que cuando Java decidió llamar a todo "método", no les importó la distinción entre una función y un método en informática teórica.

Bitcoin M
fuente
3
Así es. Hasta e incluyendo Java 7, ni siquiera encontrará la palabra "función" en la Especificación
Erwin Bolwidt
44
Por mucho que me guste la simplicidad de esta respuesta, creo que la respuesta de Radiodef está más encaminada porque menciona el punto clave de que la clase misma actúa como un objeto. Gracias de cualquier forma.
Carcigenicate
2
Curiosamente, esto es paralelo a las decisiones de los lenguajes anteriores de no diferenciar entre funciones y subrutinas.
Random832
44
Estoy desagradablemente sorprendido de que esta respuesta haya recibido tantos votos positivos. En primer lugar, esta respuesta pretende que los métodos de clase no existen. En segundo lugar, este no es un concepto introducido en Java. Los métodos de clase ya existían en Smalltalk, por ejemplo, que estuvo allí durante décadas antes de que Java se convirtiera en una cosa.
Malcolm
1
@ Malcolm Tengo que estar de acuerdo contigo. Después de considerar las otras respuestas, esto parece incorrecto. No es apatía por parte del creador de Java, a menos que realmente no les importara, pero de todos modos terminaron nombrándolo correctamente.
Carcigenicate
26

Los métodos estáticos no son exactamente funciones, la diferencia es sutil, pero importante.

Un método estático que usa solo parámetros de entrada dados es esencialmente una función.

Pero los métodos estáticos pueden acceder a variables estáticas y otras funciones estáticas (también usando variables estáticas), por lo que los métodos estáticos pueden tener un estado que es fundamentalmente diferente a una función que, por definición, no tiene estado . (ADENDA: Si bien los programadores a menudo no son tan estrictos con el uso de "función" como definición, una función estricta en informática solo puede acceder a los parámetros de entrada). Por lo tanto, definir este caso de acceso a campos estáticos no es válido decir que los métodos estáticos son siempre funciones.

Otra diferencia que justifica el uso del "método estático" es que puede definir en derivadas de C funciones globales y variables globales a las que se puede acceder desde cualquier lugar. Si no puede acceder a la clase que contiene métodos estáticos, los métodos también son inaccesibles. Por lo tanto, los "métodos estáticos" están limitados en su alcance por diseño en contraste con las funciones globales.

Thorsten S.
fuente
2
Me gusta esta respuesta, pero me gustaría entender mejor algunas cosas. ¿No es esto más una función "pura" frente a una "efecto secundario", en lugar de una función frente al método? ¿O es que un método es así debido a los efectos secundarios? Solo estoy haciendo una lluvia de ideas aquí.
Nadir Sampaoli
2
Esta respuesta es correcta. Sin embargo, se podría argumentar que las funciones en muchos idiomas (¿la mayoría?) Pueden acceder a variables globales, por lo que a menudo no son estrictamente sin estado (la misma entrada, la misma salida). Y en el caso de los métodos estáticos de Java, acceder a variables de clase podría considerarse equivalente a acceder a variables "globales" (es decir, no locales a una función / método), siendo la instancia de clase una especie de espacio de nombres.
leonbloy
1
@leonbloy Los lenguajes de programación funcionales puros como Haskell son completamente sin estado; No hay nada que pueda llamarse una variable global.
Thorsten S.
17

En Java, una clase definida por el usuario es en realidad una instancia de una subclase de java.lang.Class.

En este sentido, los métodos estáticos se adjuntan a una instancia de una clase conceptual: se adjuntan a una instancia de una subclase de java.lang.Class.

Con esto en mente, el término "método de clase" (un nombre alternativo para los métodos estáticos de Java) comienza a tener sentido. Y el término "método de clase" se puede encontrar en muchos lugares: Objetivo C, Smalltalk y JLS, por nombrar solo algunos.

Mike Clark
fuente
¿Es posible tener dos instancias de esta subclase?
Random832
Por supuesto, puede cargar una clase en diferentes cargadores de clases (la razón de obtener ClassCastExceptions con el mensaje "no se puede convertir CustomClass en CustomClass").
Dunni
2
@ Random832 - más o menos. Puede tener dos (o más) instancias de la misma subclase de Clase en la misma JVM, siempre que cada instancia tenga su propio cargador de clases separado. No puede crear una instancia de la misma subclase de clase más de una vez por cargador de clases. Se vuelve un poco confuso y las analogías con los conceptos clásicos de OO comienzan a estirarse un poco en este punto.
Mike Clark
@MikeClark si hago eso, ¿son realmente lo mismo? Por ejemplo, ¿la subclase de clase será la misma clase incluso si la clase en sí es una instancia diferente de la misma? Los cargadores de clases son bastante confusos para mí. ¿Podría llamar (sin reflexión) un método estático de la instancia de un cargador de clases de una clase desde la instancia de otro cargador de clases de la misma clase, haciendo pasar una referencia a ella? ¿Qué pasa si tienen diferentes métodos?
Random832
1
@ Random832 "¿Más o menos?" Desde un punto de vista puramente OO, ¿hay dos instancias de una clase realmente exactamente iguales? Al menos dos instancias idénticas de la misma clase tendrán direcciones diferentes. De lo contrario, ¿cómo podemos tener dos de una cosa? Lo único que es exactamente lo mismo que algo es la cosa misma.
Mike Clark
11

En informática, la función se asigna claramente a un método estático. Pero el "método" de una clase es un poco genérico, como "miembro" (miembro de campo, miembro de método). Hay palabras como

Los miembros de datos y los miembros de métodos tienen dos espacios de nombre separados: .x y .x () pueden coexistir.

Entonces, la razón es que, como dijo el filósofo Ludwig Wittgenstein, el lenguaje es una herramienta con diferentes contextos. "Método" es un buen apodo en la cita anterior para clasificar a un "miembro".

Joop Eggen
fuente
9

Tu pensamiento es correcto y tiene sentido. Simplemente no es una terminología establecida en la comunidad Java. Permítanme explicar algunos aspectos internos que pueden ayudar a entender por qué subsiste la terminología.

Java es un lenguaje orientado a objetos basado en clases. Un método siempre es miembro de una clase o instancia (esta es una declaración general válida para otros lenguajes de programación también). Pensamos que clase e instancia son ambos objetos.

Método de instancia (dinámico)

No puede invocar este método directamente desde una clase, debe crear una instancia. Cada instancia hace referencia a ese método. Puede sobrescribir una definición de método con exactamente la misma firma de método (cuando se subclasifican), es decir, los puntos de referencia a un método diferente (que tiene la misma firma, pero puede tener un cuerpo de método diferente). El método es dinámico.

Método de clase (estático)

Solo puede invocar este método directamente desde la clase, es decir, no necesita crear una instancia de esa clase. Solo hay una definición global de ese método en todo el programa. No puede sobrescribir exactamente la misma firma de método cuando el método se declara estático, porque solo hay una definición válida para todo el programa. Tenga en cuenta que el método es miembro del propio objeto de clase, las instancias tienen la misma referencia única (y fija) a ese método.

Ely
fuente
7

Aquí hay otra versión de la terminología, usando Scala como mnemónico:
en Scala tiene objects, que son instancias únicas de una clase definida implícitamente1 .

Según su definición, podemos llamar a estas subrutinas que pertenecen a los object métodos , ya que operan en una sola instancia de la clase.
Además, el objeto también definirá la clase A y creará todos los métodos en el objeto A como métodos estáticos en la clase A (para interactuar con Java) [2] .

Por lo tanto, podemos decir que los métodos estáticos de la clase A de Java acceden a los mismos miembros que la instancia Singleton de Scala, que según su definición merecen llamarse métodos (estáticos) de la clase A.

mucaho
fuente
Gran comparacion. Conozco a Scala, así que tu objectreferencia tiene mucho sentido. Gracias.
Carcigenicar
2

Por supuesto, la principal diferencia es que el método puede usar campos estáticos, no solo parámetros del método. Pero hay uno adicional: ¡polimorfismo! Los resultados de la evaluación Clase A.doTheSameStaticMethod () y ClassB.doTheSameStaticMehod () dependerán de la clase. En este caso la función es impotente.

Павел Бивойно
fuente
1

Cada clase tiene un objeto para representarlo que es una instancia de una subclase de la Classclase. Los métodos estáticos son realmente métodos de instancia en estos objetos que son instancias de una subclase de Clase. Tienen acceso al estado en forma de campos estáticos, por lo que no se limitan a ser solo funciones (sin estado). Son métodos.

Bohemio
fuente