Perché un metodo statico è considerato un metodo?


135

Sto scrivendo una spiegazione per un po 'di codice per un corso e ho accidentalmente usato le parole methode in modo functionintercambiabile. Ho deciso di tornare indietro e correggere la formulazione, ma ho incontrato un buco nella mia comprensione.

Da quanto ho capito, una subroutine è un functionse non agisce su un'istanza di una classe (il suo effetto è limitato al suo input / output esplicito), ed è un methodse opera su un'istanza di una classe (può portare effetti collaterali sull'istanza che lo rendono impuro).

C'è una buona discussione qui sull'argomento. Si noti che dalle definizioni della risposta accettata, una statica methoddovrebbe effettivamente essere una funzione perché un'istanza non viene mai passata implicitamente e non ha accesso ai membri di alcuna istanza.

Con questo, però, non dovrebbero methodsessere le funzioni statiche ?

Per loro definizione non agiscono su particolari istanze di una classe; sono solo "legati" alla classe a causa della relazione. Ho visto alcuni siti di bell'aspetto che si riferiscono a subroutine statiche come "metodi" ( Oracle , Fredosaurus , ProgrammingSimplified ), quindi o stanno tutti trascurando la terminologia, o mi manca qualcosa (la mia ipotesi è la seconda) .

Mi piacerebbe essere sicuro di usare la formulazione corretta.
Qualcuno può chiarire questo?


2
Ho sempre pensato che fosse funzione in php e metodo in Java. Fondamentalmente la stessa cosa con nomi diversi
JK

19
C'è una differenza tra l'informatica teorica e il modo in cui una lingua lo applica. Il JLS non fa alcuna distinzione e lo chiama un metodo.
Jeroen Vannevel,


2
Potrebbe essere di interesse per un'occhiata alle definizioni di "funzione" e "metodo" in Python, in cui v'è una differenza: in sostanza, una funzione è un pezzo di codice con una tabella di simboli e di una convenzione di chiamata, mentre un metodo è quello si ottiene quando si inserisce una funzione in una classe. La differenza è abbastanza sottile, anche per le persone che conoscono Python.
David Z,

2
Quando stavo imparando la teoria, ho imparato che la funzione restituisce un valore e la procedura no. Poi ho imparato i metodi di funzioni e procedure di chiamate java. Ora sto provando la programmazione funzionale e una funzione è idempotente. I termini cambiano significato sul contesto.
emory

Risposte:


123

Questa citazione da 8.4.3.2 può aiutare:

Un metodo dichiarato staticviene chiamato metodo di classe .

Un metodo non dichiarato staticviene chiamato metodo di istanza [...].

  • Metodi di classe: associati a una classe.
  • Metodi di istanza: associati a un'istanza.

Java vuole solo "pensare orientato agli oggetti". Inoltre, i metodi statici hanno accesso a un ambito circostante che può includere lo stato. In un certo senso, la classe è come un oggetto stesso.


Detto questo, mentre "funzione" è tecnicamente corretta come unità di esecuzione in Java, la nomenclatura preferita praticamente in tutto Java è "metodo", poiché tutte le funzioni Java fanno parte di una classe o interfaccia (esclusi lambdas, e forse alcune altre cose di cui non sono a conoscenza).
Fucile Ninja

1
Le lambda sono in realtà classi interne anonime con l' @FunctionalInterfaceannotazione e con 1 metodo sotto il cofano. Una lambda è solo zucchero sintattico e al riguardo non c'è nulla di nuovo.
Adam Arold,

1
@AdamArold Lambdas sono un po 'più fantasiosi di una classe interna anonima. Ad esempio, lambda non catturanti possono condividere un'istanza attraverso più valutazioni di una determinata espressione. (Ma hai ragione, alla fine vengono compilati con metodi statici e di istanza.)
Radiodef,

@Radiodef Forse un modo migliore per pronunciare la frase sarebbe "Tutte le espressioni lambda possono essere sostituite con espressioni non lambda equivalenti, senza apportare modifiche a file diversi da quello contenente l'espressione lambda" o qualcosa del genere.
user253751,

4
Sono imbarazzato. Vengo da Scala e riesco ancora a perdere il fatto che la classe stessa è simile ad un oggetto. Grazie.
Carcigenicato

80

La semplice risposta è che quando Java ha deciso di chiamare tutto un "metodo", non gli importava della distinzione tra una funzione e un metodo nell'informatica teorica.


3
Giusto. Fino a Java 7 incluso non troverai nemmeno la parola "funzione" nelle Specifiche
Erwin Bolwidt,

4
Per quanto mi piaccia la semplicità di questa risposta, penso che la risposta di Radiodef sia più giusta perché menziona il punto chiave che la classe stessa funge da oggetto. Grazie ugualmente.
Carcigenicato

2
È interessante notare che ciò è accompagnato dalle decisioni delle lingue precedenti di non distinguere tra funzioni e subroutine.
Casuale 832,

4
Sono spiacevolmente sorpreso che questa risposta abbia ottenuto così tanti voti positivi. In primo luogo, questa risposta finge che non esistano metodi di classe. In secondo luogo, questo non è certo un concetto introdotto in Java. I metodi di classe esistevano già in Smalltalk, per esempio, che era lì da decenni prima che Java diventasse una cosa.
Malcolm,

1
@Malcolm Sono d'accordo con te. Dopo aver considerato le altre risposte, questo sembra sbagliato. Non è un'apatia da parte del creatore di Java, a meno che non gliene importasse davvero, ma alla fine lo hanno nominato correttamente.
Carcigenicato

26

I metodi statici non sono esattamente funzioni, la differenza è sottile, ma importante.

Un metodo statico che utilizza solo determinati parametri di input è essenzialmente una funzione.

Ma i metodi statici possono accedere a variabili statiche e altre funzioni statiche (anche usando variabili statiche), quindi i metodi statici possono avere uno stato che è fondamentalmente diverso da una funzione che per definizione è apolide . (ADDENDUM: Mentre i programmatori spesso non sono così severi con l'uso di "funzione" come definizione, una funzione rigorosa in informatica può accedere solo ai parametri di input). Quindi, definendo questo caso di accesso ai campi statici, non è valido dire che i metodi statici sono sempre funzioni.

Un'altra differenza che giustifica l'uso del "metodo statico" è che è possibile definire in C derivate funzioni globali e variabili globali a cui è possibile accedere ovunque. Se non è possibile accedere alla classe che contiene metodi statici, anche i metodi sono inaccessibili. Quindi i "metodi statici" sono limitati nel loro ambito di progettazione in contrasto con le funzioni globali.


2
In un certo senso mi piace questa risposta, ma vorrei capire meglio alcune cose. Non è più una funzione "pura" vs "efficace", piuttosto che una funzione rispetto al metodo? O è che un metodo è tale a causa degli effetti collaterali? Sto solo facendo un brainstorming qui.
Nadir Sampaoli,

2
Questa risposta è giusta Tuttavia, si potrebbe sostenere che le funzioni in molte (la maggior parte?) Lingue possono accedere a variabili globali, quindi spesso non sono rigorosamente apolidi (stesso input, stesso output). E nel caso dei metodi statici Java, accedere alle variabili di classe potrebbe essere considerato equivalente all'accesso a variabili "globali" (cioè non locali a una funzione / metodo) - con l'istanza della classe che è una specie di spazio dei nomi.
leonbloy,

1
@leonbloy Pure I linguaggi di programmazione funzionale come Haskell sono completamente apolidi; non c'è niente che possa essere chiamato una variabile globale.
Thorsten S.

17

In Java, una classe definita dall'utente è in realtà un'istanza di una sottoclasse di java.lang.Class.

In questo senso, i metodi statici sono collegati a un'istanza di una classe concettuale: sono collegati a un'istanza di una sottoclasse di java.lang.Class.

Con questo in mente, il termine "metodo di classe" (un nome alternativo per i metodi statici di Java) inizia a dare un senso. E il termine "metodo di classe" può essere trovato in molti punti: Obiettivo C, Smalltalk e JLS - solo per citarne alcuni.


È possibile avere due istanze di questa sottoclasse?
Casuale 832,

Naturalmente, è possibile caricare una classe in diversi classloader (il motivo per ottenere ClassCastExceptions con il messaggio "impossibile eseguire il cast di CustomClass in CustomClass").
Dunni,

2
@ Random832 - sorta di. È possibile avere due (o più) istanze della stessa sottoclasse Class nella stessa JVM, purché ogni istanza abbia il proprio programma di caricamento classi separato. Non è possibile creare un'istanza della stessa sottoclasse di classe più di una volta per classloader. Diventa un po 'confuso e le analogie con i concetti OO classici iniziano a diventare un po' sottili a questo punto.
Mike Clark,

@MikeClark se lo faccio, sono davvero gli stessi? Ad esempio, la sottoclasse Class sarà la stessa classe anche se la stessa classe ne è un'istanza diversa? I classloader sono piuttosto confusi per me. Potrei chiamare (senza riflessione) un metodo statico dell'istanza di un classloader di una classe dall'istanza di un altro classloader della stessa classe, facendo riferimento ad essa? E se avessero metodi diversi?
Casuale 832,

1
@ Random832 "Sorta di?" Da un puramente OO punto la teoria di vista, sono delle due istanze di una classe mai veramente esattamente la stessa cosa? Almeno due istanze altrimenti identiche della stessa classe avranno indirizzi diversi. Altrimenti, come possiamo avere due cose? L'unica cosa che è esattamente la stessa cosa di qualcosa, è la cosa stessa.
Mike Clark,

11

Nell'informatica la funzione è chiaramente associata a un metodo statico. Ma "metodo" di una classe è un po 'generico, come "membro" (membro del campo, membro del metodo). Ci sono parole come

I membri dei dati e i membri del metodo hanno due spazi dei nomi separati: .xe .x () possono coesistere.

Quindi la ragione è che, come diceva il filosofo Ludwig Wittgenstein, la lingua è uno strumento con contesti diversi. "Metodo" è un bel moniker nella citazione sopra per classificare un "membro".


9

Il tuo pensiero è giusto ed ha senso. Non è solo una terminologia consolidata nella comunità Java. Vorrei spiegare alcuni interni che possono aiutare a capire perché sussiste la terminologia.

Java è un linguaggio orientato agli oggetti basato sulla classe. Un metodo è sempre membro di una classe o istanza (questa è un'istruzione generale valida anche per altri linguaggi di programmazione). Pensiamo che classe e istanza siano entrambi oggetti.

Metodo di istanza (dinamico)

Non è possibile richiamare questo metodo direttamente da una classe, è necessario creare un'istanza. Ogni istanza fa riferimento a quel metodo. È possibile sovrascrivere la definizione di un metodo con la stessa identica firma del metodo (durante la sottoclasse), ovvero il riferimento punta a un metodo diverso (che ha la stessa firma, ma può avere un corpo del metodo diverso). Il metodo è dinamico

Metodo di classe (statico)

Puoi solo invocare questo metodo direttamente dalla classe, ovvero non è necessario creare un'istanza di quella classe. C'è solo una definizione globale di quel metodo nell'intero programma. Non è possibile sovrascrivere la stessa identica firma del metodo quando il metodo viene dichiarato statico, poiché esiste solo una definizione valida per l'intero programma. Si noti che il metodo è membro dell'oggetto classe stesso, le istanze hanno tutti lo stesso riferimento univoco (e corretto) a quel metodo.


7

Ecco un'altra interpretazione della terminologia, usando Scala come mnemonico:
in Scala hai objects, che sono istanze singleton di una classe implicitamente definita1 .

Secondo la tua definizione, possiamo chiamare queste subroutine appartenenti ai object metodi , in quanto operano su una singola istanza della classe.
Inoltre l'oggetto definirà anche la classe A e creerà tutti i metodi nell'oggetto A come metodi statici sulla classe A (per l'interfacciamento con Java) [2] .

Pertanto possiamo dire che i metodi statici della classe A di Java accedono agli stessi membri dell'istanza singleton di Scala, che per la tua definizione quindi meritano di essere chiamati metodi (statici) di classe A.


Grande confronto. Conosco Scala, quindi il tuo objectriferimento ha molto senso. Grazie.
Carcigenicato

2

Naturalmente, la differenza principale è che il metodo può utilizzare campi statici, non solo i parametri del metodo. Ma ce n'è uno aggiuntivo: il polimorfismo! I risultati della valutazione La classe A.doTheSameStaticMethod () e ClassB.doTheSameStaticMehod () dipenderà dalla classe. In questo caso la funzione è impotente.


1

Ogni classe ha un oggetto per rappresentarlo che è un'istanza di una sottoclasse della Classclasse. I metodi statici sono in realtà metodi di istanza su questi oggetti che sono istanze di una sottoclasse di Class. Hanno accesso allo stato sotto forma di campi statici, quindi non si limitano ad essere solo funzioni (senza stato). Sono metodi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.