Por que um método estático é considerado um método?

135

Estou escrevendo uma explicação para algum código de um curso e uso acidentalmente as palavras methode de forma functionintercambiável. Decidi voltar e corrigir o texto, mas encontrei um buraco no meu entendimento.

Pelo que entendi, uma sub-rotina é functionse não age em uma instância de uma classe (seu efeito é restrito a sua entrada / saída explícita) e é methodse opera em uma instância de uma classe (pode efeitos colaterais na instância que a tornam impura).

Há uma boa discussão aqui sobre o assunto. Observe que, pelas definições da resposta aceita, uma estática methoddeve realmente ser uma função porque uma instância nunca é passada implicitamente e não tem acesso aos membros de nenhuma instância.

Com isso em mente, a estática não deveria methodsrealmente ser funções?

Por sua definição, eles não agem em instâncias particulares de uma classe; eles só estão "vinculados" à classe por causa de relação. Eu já vi alguns sites com boa aparência que se referem a sub-rotinas estáticas como "métodos" ( Oracle , Fredosaurus , ProgrammingSimplified ); portanto, todos estão ignorando a terminologia ou estou perdendo alguma coisa (meu palpite é o último). .

Gostaria de ter certeza de que estou usando as palavras corretas.
Alguém pode esclarecer isso?

Carcinogenicado
fonte
2
Eu sempre pensei que era função em php e método em Java. Basicamente a mesma coisa com nomes diferentes
JK
19
Há uma diferença entre a ciência da computação teórica e como uma linguagem a aplica. O JLS não faz distinção e o chama de método.
Jeroen Vannevel
2
Pode ser de interesse para olhar para as definições de "função" e "método" em Python, onde não é uma diferença: basicamente, uma função é um pedaço de código com uma tabela de símbolos e uma convenção de chamada, enquanto que um método é o que você obtém quando coloca uma função em uma classe. A diferença é bastante sutil, mesmo para pessoas que conhecem Python.
David Z
2
Quando eu estava aprendendo teoria, aprendi que a função retorna um valor e o procedimento não. Então eu aprendi Java chama funções e métodos de procedimentos. Agora estou tentando programmjng funcional e uma função é idempotente. Os termos mudam de significado no contexto.
Emory 23/05

Respostas:

123

Esta citação do 8.4.3.2 podem ajudar:

Um método declarado staticé chamado de método de classe .

Um método que não é declarado staticé chamado de método de instância [...].

  • Métodos de classe: associados a uma classe.
  • Métodos de instância: associados a uma instância.

Java só quer que você "pense orientado a objetos". Além disso, os métodos estáticos têm acesso a um escopo circundante que pode incluir o estado. De certa forma, a classe é como um objeto em si.

Radiodef
fonte
Dito isto, enquanto "função" é tecnicamente correta como uma unidade de execução em Java, a nomenclatura preferida em praticamente todo Java é "método", pois todas as funções Java fazem parte de uma classe ou interface (excluindo lambdas e talvez outras coisas das quais não estou ciente).
Shotgun Ninja
1
Na verdade, as lambdas são classes internas anônimas com a @FunctionalInterfaceanotação e com 1 método sob o capô. Um lambda é apenas açúcar sintático e, nesse sentido, não há nada de novo.
Adam Arold
1
O @AdamArold Lambdas é um pouco mais sofisticado do que uma classe interna anônima. Por exemplo, lambdas que não capturam podem compartilhar uma instância entre várias avaliações de uma expressão específica. (Mas você está certo eles finalmente se compilado para métodos estáticos e de instância.)
Radiodef
@Radiodef Talvez uma maneira melhor de expressar isso seria "Todas as expressões lambda podem ser substituídas por expressões não-lambda equivalentes, sem fazer alterações em arquivos que não contenham a expressão lambda" ou algo assim.
User253751 23/05
4
Eu estou envergonhado. Eu sou proveniente de Scala e ainda consegui perder o fato de que a classe em si é parecida com um objeto. Obrigado.
Carcigenicate
80

A resposta simples é que quando o Java decidiu chamar tudo de "método", eles não se preocuparam com a distinção entre uma função e um método na ciência da computação teórica.

Bitcoin M
fonte
3
Está certo. Até e incluindo o Java 7, você nem encontrará a palavra "função" na Especificação
Erwin Bolwidt
4
Por mais que eu goste da simplicidade dessa resposta, acho que a resposta de Radiodef está mais no caminho certo, porque menciona o ponto principal de que a própria classe atua como um objeto. Obrigado mesmo assim.
Carcigenicate
2
Curiosamente, isso é paralelo às decisões dos idiomas anteriores de não diferenciar funções e sub-rotinas.
Random832
4
Estou desagradavelmente surpreso que essa resposta tenha recebido muitos votos. Primeiramente, esta resposta finge que os métodos de classe não existem. Em segundo lugar, esse dificilmente é um conceito introduzido em Java. Os métodos de classe já existiam no Smalltalk, por exemplo, que estava lá por décadas antes de o Java se tornar uma coisa.
Malcolm
1
@ Malcolm eu tenho que concordar com você. Depois de considerar as outras respostas, isso parece errado. Não é apatia por parte do criador do Java, a menos que eles realmente não se importem, mas acabem nomeando-o corretamente, independentemente.
Carcigenicate
26

Métodos estáticos não são exatamente funções, a diferença é sutil, mas importante.

Um método estático usando apenas determinados parâmetros de entrada é essencialmente uma função.

Mas os métodos estáticos podem acessar variáveis ​​estáticas e outras funções estáticas (também usando variáveis ​​estáticas); portanto, os métodos estáticos podem ter um estado que é fundamentalmente diferente de uma função que, por definição, é sem estado . (ADENDA: Embora os programadores geralmente não sejam tão rigorosos com o uso de "função" como definição, uma função estrita na ciência da computação pode acessar apenas parâmetros de entrada). Portanto, definindo este caso de acesso a campos estáticos, não é válido dizer que métodos estáticos são sempre funções.

Outra diferença que justifica o uso do "método estático" é que você pode definir em C derivados funções globais e variáveis ​​globais que podem ser acessadas em qualquer lugar. Se você não puder acessar a classe que contém métodos estáticos, os métodos também estarão inacessíveis. Portanto, os "métodos estáticos" são limitados em seu escopo pelo design, em contraste com as funções globais.

Thorsten S.
fonte
2
Eu meio que gosto dessa resposta, mas gostaria de entender melhor algumas coisas. Não é mais uma função "pura" vs "com efeito colateral", em vez de função vs método? Ou será que um método é assim por causa dos efeitos colaterais? Estou apenas fazendo um brainstorming aqui.
Nadir Sampaoli 23/05
2
Esta resposta está certa. No entanto, pode-se argumentar que as funções em muitos idiomas (a maioria?) Podem acessar variáveis ​​globais, portanto, muitas vezes não são estritamente sem estado de estado (mesma entrada, mesma saída). E no caso de métodos estáticos Java, acessar variáveis ​​de classe pode ser considerado equivalente a acessar variáveis ​​"globais" (isto é, não locais para uma função / método) - com a instância de classe sendo uma espécie de espaço para nome.
Leonbloy 24/05
1
As linguagens de programação funcionais puras do @leonbloy , como Haskell, são completamente sem estado; não há nada que possa ser chamado de variável global.
Thorsten S.
17

Em Java, uma classe definida pelo usuário é na verdade uma instância de uma subclasse de java.lang.Class.

Nesse sentido, métodos estáticos são anexados a uma instância de uma classe conceitual: eles são anexados a uma instância de uma subclasse de java.lang.Class.

Com isso em mente, o termo "método de classe" (um nome alternativo para os métodos estáticos de Java) começa a fazer sentido. E o termo "método de classe" pode ser encontrado em muitos lugares: Objetivo C, Smalltalk e JLS - para citar apenas alguns.

Mike Clark
fonte
É possível ter duas instâncias dessa subclasse?
#Registrado em
Obviamente, você pode carregar uma classe em diferentes carregadores de classes (o motivo de obter ClassCastExceptions com a mensagem "não é possível converter CustomClass em CustomClass").
dunni 22/05
2
@ Random832 - mais ou menos. Você pode ter duas (ou mais) instâncias da mesma subclasse de Classe na mesma JVM, desde que cada instância tenha seu próprio carregador de classes separado. Você não pode instanciar a mesma subclasse de classe mais de uma vez por carregador de classes. Fica um pouco confuso e as analogias com os conceitos clássicos de OO começam a ficar um pouco mais finas neste momento.
Mike Clark
@ MikeClark, se eu fizer isso, eles são realmente iguais? Como, a subclasse Class será da mesma classe, mesmo que a própria classe seja uma instância diferente dela? Os carregadores de classes são bem confusos para mim. Eu poderia chamar (sem reflexão) um método estático da instância de um classloader de uma classe da instância de outro classloader da mesma classe, tendo uma referência a ela passada? E se eles tiverem métodos diferentes?
Random832
1
@ Random832 "Mais ou menos?" Do ponto de vista puramente da teoria do OO, existem duas instâncias de uma classe que são exatamente iguais? No mínimo, duas instâncias idênticas da mesma classe terão endereços diferentes. Caso contrário, como podemos ter duas coisas? A única coisa exatamente igual a alguma coisa é a própria coisa.
Mike Clark
11

Na ciência da computação, a função é claramente mapeada para um método estático. Mas o "método" de uma classe é um pouco genérico, como "membro" (membro do campo, membro do método). Existem expressões como

Membros de dados e membros de método têm dois espaços de nome separados: .x e .x () podem coexistir.

Portanto, a razão é que, como disse o filósofo Ludwig Wittgenstein, a linguagem é uma ferramenta com contextos diferentes. "Método" é um bom apelido na citação acima para categorizar um "membro".

Joop Eggen
fonte
9

Seu pensamento está certo e faz sentido. Não é apenas terminologia estabelecida na comunidade Java. Deixe-me explicar alguns elementos internos que podem ajudar a entender por que a terminologia subsiste.

Java é uma linguagem orientada a objetos baseada em classe. Um método é sempre membro de uma classe ou instância (esta é uma declaração geral válida para outras linguagens de programação também). Pensamos em classe e instância sendo os dois objetos.

Método de instância (dinâmico)

Você não pode invocar esse método diretamente de uma classe, você deve criar uma instância. Cada instância faz referência a esse método. Você pode sobrescrever uma definição de método com exatamente a mesma assinatura de método (ao subclassificar), ou seja, a referência aponta para um método diferente (que tem a mesma assinatura, mas pode ter um corpo de método diferente). O método é dinâmico.

Método de classe (estático)

Você só pode invocar esse método diretamente da classe, ou seja, não precisa criar uma instância dessa classe. Existe apenas uma definição global desse método em todo o programa. Você não pode substituir exatamente a mesma assinatura de método quando o método é declarado estático, porque há apenas uma definição válida para todo o programa. Observe que o método é membro do próprio objeto de classe, as instâncias têm a mesma referência exclusiva (e correção) a esse método.

Ely
fonte
7

Aqui está outra visão da terminologia, usando Scala como um mnemônico:
No Scala, você tem objects, que são instâncias únicas de uma classe definida implicitamente1 .

De acordo com sua definição, podemos chamar essas sub-rotinas pertencentes aos object métodos , pois operam em uma única instância da classe.
Além disso, o objeto também definirá a classe A e criará todos os métodos no objeto A como métodos estáticos na classe A (para interface com Java) [2] .

Portanto, podemos dizer que os métodos estáticos da classe Java A acessam os mesmos membros da instância singala Scala, que por sua definição merecem ser chamados métodos (estáticos) da classe A.

mucaho
fonte
Ótima comparação. Eu conheço Scala, então sua objectreferência faz muito sentido. Obrigado.
Carcigenicate
2

Obviamente, a principal diferença é - o método pode usar campos estáticos, não apenas os parâmetros do método. Mas há um polimorfismo adicional! Resultados da avaliação As classes A.doTheSameStaticMethod () e ClassB.doTheSameStaticMehod () dependerão da classe. Nesse caso, a função é impotente.

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

Cada classe tem um objeto para representá-lo, que é uma instância de uma subclasse da Classclasse. Métodos estáticos são realmente métodos de instância nesses objetos que são instâncias de uma subclasse de Class. Eles têm acesso ao estado na forma de campos estáticos, portanto, não estão restritos a serem apenas funções (sem estado). Eles são métodos.

Boêmio
fonte