2012-08-23 8 views
6

Date un'occhiata a questo semplice classe Sto costruendo la base per memorizzare i risultati degli algoritmi di stringa corrispondente:Perché questi oggetti non sono uguali per impostazione predefinita in D?

/** Match of a single pattern in full to a single text. */ 
class Match { 
    uint Tpos; 

    this(in uint Tpos) { this.Tpos = Tpos; } 

    override string toString() { 
     return text("Match: [email protected]",Tpos); 
    } 
} 

Qui è dove le cose si fanno strane:

auto m1 = new Match(1), m2 = new Match(1); 
writeln(m1.toHash()); 
writeln(m2.toHash()); 
writeln(m1 == m2); 

stampe

4464528 
4464512 
false 

Non vedo alcun motivo per cui questi due oggetti non dovrebbero essere considerati uguali per impostazione predefinita. Suppongo di poter scrivere una funzione personalizzata toHash() e opEquals(), ma sembra eccessivo. Secondo Andrei Alexandrescu book sul linguaggio di programmazione D (ottimo libro!), "Per impostazione predefinita, l'hash viene calcolato utilizzando la rappresentazione bit a bit dell'oggetto." Qualche idea là fuori?

risposta

8

Dal codice sorgente (dmd2/src/druntime/src/object_.d):

class Object 
{ 
/* snip */ 
    /** 
    * Compute hash function for Object. 
    */ 
    hash_t toHash() @trusted nothrow 
    { 
     // BUG: this prevents a compacting GC from working, needs to be fixed 
     return cast(hash_t)cast(void*)this; 
    } 
/* snip */ 
    /** 
    * Returns !=0 if this object does have the same contents as obj. 
    */ 
    equals_t opEquals(Object o) 
    { 
     return this is o; 
    } 
} 

Quindi la risposta è semplicemente che è il modo in cui il codice è scritto - fanno un controllo di identità piuttosto che un controllo del contenuto. Perché è così? Non lo so, ma credo sia stato semplice scrivere in origine e funziona abbastanza bene che nessuno si è preso la briga di tornare su di esso e cambiarlo.

Nel newsgroup, si è discusso di rimuovere completamente queste funzioni da Object, quindi se si desidera == sulle classi, sarà necessario implementare qualcosa. Ma il tempo impiegato dai newsgroup per parlare diventa azione quando si tratta di cose come questa di solito è piuttosto lunga. E potrebbero cambiare idea.

Il modo migliore di utilizzare l'uguaglianza di classe attualmente e probabilmente nel prossimo futuro è scrivere il proprio metodo opEquals nella classe.

+0

Grazie per il codice sorgente e approfondimenti. Non ho realizzato == rispetto all'identità per impostazione predefinita. Ho finito per riscriverlo come una struct in ogni caso, perché voglio copiare l'oggetto per valore la maggior parte del tempo. – denine99

4

La risposta è semplice: per impostazione predefinita, opEquals per gli oggetti confronta gli indirizzi degli oggetti. È necessario che sostituisca se si desidera la semantica del valore (o si utilizza semplicemente un struct).

Nota a margine: l'utilizzo di in non è corretto. in è l'abbreviazione di scope const dove scope significa "Non eseguirò l'escape di questo parametro fuori dal mio stack frame" (che si esegue assegnandolo a un campo di classe). Sfortunatamente il compilatore non lo applica ancora, ecco perché non hai ricevuto un errore.

+2

Non ne sono sicuro, ma penso che lo scope riguardi l'escaping di riferimenti (o puntatori) e che sia legale copiare gli argomenti del puro valore dell'ambito in variabili esterne. – cybevnm

+3

'scope' (e quindi' in') sui parametri di funzione dovrebbe impedire ai riferimenti associati a quell'argomento di eseguire l'escape della funzione (che includerebbe l'assegnazione a una variabile membro) - anche se è vero che i controlli non sono stati correttamente implementati proprio adesso. Tuttavia, in questo caso particolare, va bene indipendentemente, perché il parametro è un 'uint', che è un tipo di valore. 'scope' non ha un significato reale per i tipi di valore - solo i tipi di riferimento - perché l'argomento viene copiato e quindi non c'è alcun riferimento alla fuga. –

+0

Suppongo che 'in' non sia il miglior modificatore qui; 'const' è un'opzione migliore, anche se con un costruttore così breve probabilmente non importa quali siano i qualificatori usati. Grazie per le informazioni su 'scope'. – denine99

Problemi correlati