Quando i vecchi dei di programmazione stavano inventando una programmazione orientata agli oggetti con le classi, decisero quando si trattava di composizione ed eredità di avere due relazioni per un oggetto: "è un" e "ha un".
Ciò ha parzialmente risolto il problema delle sottoclassi rispetto alle classi principali, ma le ha rese utilizzabili senza interrompere il codice. Poiché un'istanza della sottoclasse "è un" oggetto superclasse e può essere sostituita direttamente per esso, anche se la sottoclasse ha più funzioni membro o membri dati, la "ha una" garantisce che eseguirà tutte le funzioni del genitore e avrà tutte le sue membri. Quindi si potrebbe dire che un Point3D "è un" Punto e un Point2D "è un" Punto se entrambi ereditano da Point. Inoltre un Point3D potrebbe essere una sottoclasse di Point2D.
La parità tra le classi è specifica del dominio del problema, tuttavia, e l'esempio sopra è ambiguo su ciò di cui il programmatore ha bisogno affinché il programma funzioni correttamente. Generalmente, vengono seguite le regole del dominio matematico e i valori dei dati generano uguaglianza se si limita l'ambito del confronto a solo in questo caso due dimensioni, ma non se si confrontano tutti i membri dei dati.
Quindi ottieni una tabella di restringimento delle uguaglianze:
Both objects have same values, limited to subset of shared members
Child classes can be equal to parent classes if parent and childs
data members are the same.
Both objects entire data members are the same.
Objects must have all same values and be similar classes.
Objects must have all same values and be the same class type.
Equality is determined by specific logical conditions in the domain.
Only Objects that both point to same instance are equal.
In genere scegli le regole più rigide che puoi che eseguiranno ancora tutte le funzioni necessarie nel tuo dominio problematico. I test di uguaglianza integrati per i numeri sono progettati per essere tanto restrittivi quanto possono essere a fini matematici, ma il programmatore ha molti modi per aggirare questo se non fosse questo l'obiettivo, inclusi arrotondamento su / giù, troncamento, gt, lt, ecc. . Gli oggetti con timestamp vengono spesso confrontati in base al tempo di generazione e quindi ogni istanza deve essere unica in modo che i confronti siano molto specifici.
Il fattore di progettazione in questo caso è determinare modi efficienti per confrontare gli oggetti. A volte un confronto ricorsivo di tutti i membri dei dati degli oggetti è ciò che devi fare e che può diventare molto costoso se hai molti e molti oggetti con molti membri dei dati. Le alternative sono solo di confrontare i valori di dati rilevanti o fare in modo che l'oggetto generi un valore di hash dei suoi membri di dati interessati per un rapido confronto con altri oggetti simili, mantenere le raccolte ordinate e potate per rendere i confronti più veloci e meno intensivi della CPU e forse consentire oggetti che sono identici nei dati da abbattere e al suo posto viene inserito un puntatore duplicato a un singolo oggetto.