2012-06-03 4 views
6

Sto imparando le basi di Smalltalk. C'è una parola chiave super che viene utilizzato per chiamare un metodo da superclasse all'interno di un metodo sottoclasse:Parola chiave "super" nel metodo classe

Object subclass: # A 
    test 
     ^1 

A subclass: # B 
    test 
     ^2 
    callSuper 
     ^super test 

Così B new callSuper viene valutato come 1.

OK. Questo è chiaro

Così ora, sto definendo una serie di metodi di classe per B classe:

createNew1 
    ^super new 
createNew2 
    ^self new 
create 
    ^self 
createSuper 
    ^super 

E loro valuta, rispettivamente a a B, a B, B e un errore (che mi mostra che super non è un cast sottoclasse ma tipo di un dispatcher di messaggi).

Perché ricevo istanze di classe B nonostante la parola chiave super? E qual è la differenza tra gli oggetti a B e B? Ho iniziato a pensare che l'oggetto B sia un'istanza speciale, singletone (proprio come gli attributi static implementati in altre lingue) della classe B, ma ancora - ho controllato ed è classe B e sottoclasse è A.

Qual è la semantica della parola chiave super nei metodi di classe? Come si differenzia dalla semantica all'interno dei metodi degli oggetti? Qual è realmente l'oggetto che può essere ottenuto chiamando il metodo self all'interno della classe?

risposta

1

Ho intenzione di rispondere a questo da solo, nonostante tutte le altre risposte siano tecnicamente corrette. Questo perché sapevo di metaclassi e sembra che io abbia una semantica corretta di super nella mia testa, eppure stavo ancora ottenendo risultati inaspettati.

Scopriamo che ho frainteso la base dell'ereditarietà in Smalltalk e come vengono chiamati i metodi.

Stavo pensando che, per tale codice ...

Object subclass: #A 
    test 
     ^'A' 
    getTest 
     ^self test 

A subclass: # B 
    test 
     ^'B' 
    runTest 
     ^super getTest 

... l'espressione B new runTest viene valutata a 'A' - che significa, il metodo della superclasse viene valutata in oggetto upcasted.

Ma non lo è.

E 'valutata per 'B', perché non c'è upcasting e quando stiamo chiamando qualsiasi metodo all'interno di un metodo della superclasse - la ricerca comincia nella classe reale dell'oggetto, non di classe da cui valutare il metodo viene.

Di conseguenza, chiamando ^self new e ^super new, pur non definendo un new in uno qualsiasi dei classess, hanno lo stesso effetto - dal momento che ciascuno di essi finisce con chiamandonew implementazione di comportamento nell'ambito della self.

+0

Se hai familiarità con C#, tutto ha senso se consideri ogni metodo Smalltalk (istanza o classe) come dichiarato come virtuale. –

+0

"L'espressione B nuovo runest è valutata come 'A'" No! Stai effettivamente valutando questo codice, o semplicemente facendo un esperimento mentale ?! Uno dei grandi vantaggi di Smalltalk è quanto sia facile fare esperimenti. Se valuti "B new runTest", vedrai che restituisce "B" –

+0

@SeanDeNigris Forse non è chiaro a causa del mio povero inglese, ma volevo scrivere, che stavo pensando che è valutato su "A" mentre in Infatti è valutato su "B" (che è scritto nel prossimo paragrafo). Proverò a modificare questo e renderlo chiaro. –

4

self e super fanno sempre riferimento allo stesso oggetto, il ricevitore corrente. L'unica differenza è che self avvia la ricerca del seguente metodo di invio nella classe del destinatario e super nella superclasse di dove è definito il metodo.

Vedere il capitolo 5 di Pharo by Example per i dettagli.

+0

Ma 'new' è definito in' A', quindi perché '^ Super new' non restituisce un oggetto' A' dal è chiamato all'interno di un oggetto di una classe 'B'? O forse non capisco appieno cosa sia la semantica di 'nuovo'? –

4

La risposta al primo esempio è errata. B new callSuper restituisce 1. Lukas ti ha dato la definizione esatta della semantica di super. È fondamentalmente un alias per "sé" che modifica la ricerca del metodo per il messaggio inviato. self message inizierà a cercare i metodi nella classe del destinatario, super message inizierà la ricerca nella superclasse della classe che definisce il metodo che contiene l'espressione super message (quindi la classe del destinatario non è rilevante in questo caso).

Nel secondo esempio, super new e self new, si chiama lo stesso metodo (definito da qualche parte nella gerarchia del comportamento) poiché questa è la definizione di metodo più vicina di nuovo in entrambi i casi. Se, tuttavia, i metodi createNew sono stati rinominati in nuovi, allora new ^self new sarebbe un ciclo infinito, mentre new ^super new chiama il metodo Behavior.

+0

Oh. Quello era un errore di battitura - stavo avendo un '1' in testa durante la richiesta. Modificato. –

3

sé e super significano la stessa cosa sia in una classe o di un oggetto, perché una classe è un oggetto ...

# createNew1 & # createNew2 sono equivalenti. Come ha spiegato Lukas, super significa semplicemente "avviare la ricerca del metodo nella mia superclasse anziché nella mia classe".Dal momento che non hai definito #nuovo in A o B, andrai a cercare tra le superclassi, trovando infine Comportamento >> # nuovo sia che inizi in A o B. #new inizia chiamando #basicNew, che crea e restituisce una nuova istanza di B (cioè "a B").

In #create & #createSuper, poiché non stai cercando nulla, self e super sono di nuovo equivalenti e significano "restituire l'oggetto corrente" (a quale errore ti riferivi per quest'ultimo?). Ora questa parte è confusa. Poiché tutto in Smalltalk è un oggetto, questo include le classi stesse. Quindi, in questo contesto, "l'oggetto corrente" è B, che è l'unica istanza della metaclass "Classe B". Se sei davvero interessato a capire, leggo più volte il capitolo 13 di Pharo By Example finché non ha senso (non ho ancora raggiunto quel punto, lol).

0

Sì, credo di aver capito ora ...
quando si invia^super-nuovo dalla classe B, è ancora invia il messaggio alla classe B, è solo che il messaggio è (super nuovo) ...
così si crea un'istanza di B
a meno che, naturalmente, se si definirebbe

A class>>new 
    ^A basicNew