Perché gli oggetti singleton sono più orientati agli oggetti?

In Programming in Scala: una guida dettagliata passo dopo passo , l’autore ha detto:

Un modo in cui Scala è più orientato agli oggetti di Java è che le classi in Scala non possono avere membri statici. Invece, Scala ha oggetti singleton.

Perché un object singleton è più orientato agli oggetti? Qual è il vantaggio di non utilizzare membri statici, ma oggetti singleton?

Cercando la “grande immagine”; la maggior parte di questo è stata trattata in altre risposte, ma non sembra esserci una singola risposta esauriente che mette tutto insieme e unisce i punti. Quindi ecco qui …

I metodi statici su una class non sono metodi su un object, questo significa che:

  1. I membri statici non possono essere ereditati da una class / tratto genitore
  2. I membri statici non possono essere utilizzati per implementare un’interfaccia
  3. I membri statici di una class non possono essere passati come argomento per alcune funzioni

    (e per i punti di cui sopra …)

  4. I membri statici non possono essere ignorati
  5. I membri statici non possono essere polimorfici

L’intero punto degli oggetti è che possono ereditare da oggetti padre, implementare interfacce ed essere passati come argomenti – i membri statici non hanno nessuna di queste proprietà, quindi non sono veramente orientati agli oggetti, sono poco più di uno spazio dei nomi.

Gli oggetti Singleton, d’altra parte, sono membri a tutti gli effetti della comunità degli oggetti.


Un’altra proprietà molto utile dei singleton è che possono essere facilmente modificati in un secondo momento per non essere singletons, questo è un refactoring particolarmente doloroso se si parte da metodi statici.

Immagina di aver progettato un programma per la stampa di indirizzi e di rappresentare le interazioni con la stampante tramite metodi statici su alcune classi, poi in seguito vuoi essere in grado di aggiungere una seconda stampante e consentire all’utente di scegliere quale utilizzare … essere un’esperienza divertente!

Gli oggetti Singleton si comportano come classi in quanto possono estendere / implementare altri tipi.

Non è ansible farlo in Java con solo classi statiche: è piuttosto zuccherino sul modello singleton Java con getInstance che consente (almeno) più spazi dei nomi / identificatori stabili e nasconde la distinzione.

Suggerimento: si chiama programmazione orientata agli oggetti.

Sul serio.

Forse mi manca qualcosa di fondamentalmente importante, ma non vedo di cosa si tratta in assoluto: gli oggetti sono più orientati agli oggetti dei non oggetti perché sono oggetti. Ha davvero bisogno di una spiegazione?

Nota: anche se suona sicuramente in questo modo, non sto davvero cercando di sembrare soddisfatto. Ho guardato tutte le altre risposte e le ho trovate terribilmente confuse. Per me, è ovvio che gli oggetti ei metodi sono più orientati agli oggetti di spazi dei nomi e procedure (che sono veramente i “metodi” statici) dalla stessa definizione di “object-oriented”.

Un’alternativa all’utilizzo di oggetti singleton sarebbe quella di rendere le classi stesse oggetti, come ad esempio Ruby, Python, Smalltalk, Newspeak.

Per i membri statici, non c’è alcun object . La class in realtà è solo un namespace.

In un singleton, c’è sempre almeno un object.

In tutta onestà, sta dividendo i capelli.

È più orientato agli oggetti nel senso che, data una class di Scala, ogni chiamata di metodo è una chiamata di metodo su quell’object. In Java, i metodi statici non interagiscono con lo stato dell’object.

Infatti, dato un object a di una class A con il metodo statico m() , è considerata una ctriggers pratica chiamare am() . Invece si consiglia di chiamare Am() (credo che Eclipse ti avviserà). I metodi statici Java non possono essere sovrascritti, possono semplicemente essere nascosti con un altro metodo:

 class A { public static void m() { System.out.println("m from A"); } } public class B extends A { public static void m() { System.out.println("m from B"); } public static void main(String[] args) { A a = new B(); am(); } } 

Cosa sarà am() stampare?

In Scala, si attaccano i metodi statici negli oggetti complementari A e B e l’intento risulterebbe più chiaro come si farebbe esplicitamente riferimento al compagno A o B.

Aggiungere lo stesso esempio in Scala:

 class A object A { def m() = println("m from A") } class B extends A object B { def m() = println("m from B") def main(args: Array[String]) { val a = new B Am() // cannot call am() } } 

C’è qualche differenza che potrebbe essere importante in alcuni scenari. In Java non è ansible sovrascrivere il metodo statico, quindi se si avesse class con metodi statici non si sarebbe in grado di personalizzare e sovrascrivere parte del suo comportamento. Se hai usato l’object singleton, puoi semplicemente colbind singleton creato dalla sottoclass.

È una cosa di marketing, davvero. Considera due esempi:

 class foo static const int bar = 42; end class class superfoo Integer bar = ConstInteger.new(42); end class 

Ora, quali sono le differenze osservabili qui?

  • in una lingua ben educata, lo spazio di archiviazione aggiuntivo creato è lo stesso.
  • Foo.bar e Superfoo.bar hanno esattamente le stesse firme, accesso e così via.
  • Superfoo.bar può essere assegnato in modo diverso, ma questo è un dettaglio di implementazione

Mi ricorda le guerre religiose di 20 anni fa sul fatto che C ++ o Java fossero “veramente” orientati agli oggetti, poiché in fin dei conti entrambi i tipi primitivi esposti non sono oggetti “realmente” – quindi, ad esempio, non puoi ereditare da int ma può da Integer .