Esiste un linguaggio di programmazione con non un albero ma un'idea di tag dietro OOP?

7

Sto pensando alle strutture ad albero, e sento che non mi piacciono. È come quando hai un negozio, poi provi a mettere tutti i prodotti in un catalogo ad albero, e poi devi posizionare un prodotto in più categorie, ora hai più routing, bla-bla. Non mi sento come se tutto al mondo potesse essere messo su un albero.

Invece, mi piace l'idea dei tag. Vorrei memorizzare tutto con i tag. Con i tag potrei fare molto di più. Posso anche simulare gli alberi se voglio. Voglio un filesystem basato su tag!

Ma hey - il paradigma OOP moderno con l'ereditarietà si basa sull'albero. Voglio vedere come è quando non hai questo seminterrato.

La cosa più vicina che ho trovato sono i mixin in alcune lingue. Sai cos'altro c'è anche su queste idee?

    
posta gnat 06.02.2011 - 21:52
fonte

9 risposte

12

Le gerarchie di ereditarietà rappresentano relazioni "is-a" - un oggetto in realtà è un altro oggetto.

Questo non è ciò che i tag rappresentano. Le categorie in un negozio non rappresentano: una relazione, è più di un "appartiene a" o, in termini di programmazione, "supporta la caratteristica xy". I tag possono cambiare , possono essere aggiunti e rimossi perché tu ne hai bisogno - le classi base non possono, poiché l'oggetto ha bisogno di esso! Gli oggetti non dipendono dai tag che tu gli dai, ma dipendono dalle loro classi base per avere un senso.

Puoi mettere un auto nella categoria "auto verdi" o "auto degli anni '60" - nessun problema, non importa - ma non può mai smettere di essere un veicolo!

Quindi, come vedi, gli alberi ereditari ei tuoi tag modellano cose completamente diverse . Uno riguarda l'oggetto stesso, l'altro su come relazioniamo gli oggetti insieme.

È vero, ci sono casi in cui ha senso che un oggetto abbia più di una classe base, ma questi sono rari e poiché supportare l'ereditarietà multipla vera causa molti altri problemi (ecco perché molte lingue OO non lo consentono), è un il modo ragionevole per modellare è-una gerarchia attraverso gli alberi.

D'altra parte, i tuoi tag sono rappresentati tramite interfacce (per cui l'implementazione di più è consentita praticamente in ogni lingua OO che conosco) - o meglio - attraverso typeclass , che può essere aggiunto o nascosto a seconda delle esigenze.

Sono d'accordo con te sul fatto che l'ereditarietà è spesso abusata in luoghi in cui le interfacce si adattano meglio, ma poiché entrambi sono in linea di principio concetti ortogonali, entrambi hanno i loro casi d'uso appropriati.

Modifica :

Sottolineo ancora typeclasses o concepts as sono probabilmente la risposta che stavi cercando, sebbene la domanda funzioni sulla falsa premessa secondo cui i tag devono sostituire l'ereditarietà.

    
risposta data 06.02.2011 - 22:35
fonte
6

Penso che il cuore del tuo problema risieda nel sistema dei tipi di linguaggio. Nelle lingue che utilizzano la tipizzazione strutturale o digitazione anatra , il tipo dell'oggetto è determinato dalla struttura (o solo parte della struttura nella digitazione anatra) del tipo invece di dover dichiarare il tipo usando l'ereditarietà. Quindi tutto ciò che serve per creare un oggetto di un certo tipo è "tag" l'oggetto con una certa struttura. Questo evita anche molti dei problemi con l'ereditarietà multipla.

Scala è un linguaggio con tipizzazione strutturale e Ruby utilizza la digitazione anatra.

"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."

    
risposta data 06.02.2011 - 22:52
fonte
3

I ruoli in Perl6 si avvicinano. Specificano un set di comportamenti con nome (o "taggato"). Perl 5 ha l'incredibile Moose , che implementa lo stesso concetto. Sono un po 'come le interfacce java, ma con l'implementazione non solo la definizione del metodo. Il concetto di ruolo era basato in parte sui tratti di smalltalk .

    
risposta data 07.02.2011 - 02:37
fonte
3

Due risposte:

  • la maggior parte del linguaggio tipizzato dinamicamente gestisce il polimorfismo separatamente dall'ereditarietà. non come il tuo "tagging", ma semplicemente "se l'oggetto può fare questo, allora può essere usato qui". In caso contrario, viene generato un errore di runtime.

  • Il linguaggio Go di Google realizza una cosa simile con le interfacce. È in qualche modo simile al concetto di interfacce Java, ma separato dall'ereditarietà: se una definizione di un oggetto ha tutti i metodi richiesti, il compilatore ne consente l'utilizzo. In effetti, le interfacce sono di tipo 'specifiche', che permettono al compilatore di controllare rigorosamente al momento della compilazione se la sostituzione è accettabile senza fare affidamento su un antenato comune.

risposta data 07.02.2011 - 03:41
fonte
2

modern OOP paradigm with inheritance is based on tree.

Controlla C ++, ha ereditarietà multipla. Certo, se questo conta dipende dalla tua definizione di "moderno"; -)

I suoi successori, Java e C # non hanno consentito l'ereditarietà multipla per ottime ragioni, ma è comunque possibile implementare più interfacce in questi. Le interfacce IMO (specialmente interfacce marker ) sono molto più vicine al concetto di tag rispetto alle classi (astratte o concrete).

    
risposta data 06.02.2011 - 22:08
fonte
1

Per me la programmazione orientata all'aspetto era sempre la cosa più vicina ai tag in OOP. Gli aspetti sono essenzialmente tag che deducono alcuni comportamenti su un metodo / classe e un metodo può avere più aspetti. Sfortunatamente Heijlsberg ha espresso più volte una certa distinzione per AOP, quindi è dubbio che nel framework non avremo mai più supporto. Esistono tuttavia delle librerie di terze parti piuttosto buone se vuoi sperimentarle

    
risposta data 06.02.2011 - 22:45
fonte
0

il problema più grande con l'inerenza multipla è il fatto che la lingua non sa quale metodo chiamare:

Class A {
  public method1 () {}
}
Class B {
  public method1 () {}
}
Class C extends A, B {
  public method2 () {}
}

Object o = new C();
o.method1();

Quale metodo1 () sarà chiamato? Saranno entrambi chiamati? In che ordine? Quindi solo alcune lingue supportano l'ereditarietà multipla.

    
risposta data 06.02.2011 - 22:38
fonte
0

Ontologicamente, l'ereditarietà è rappresentata da un grafo aciclico diretto delle relazioni is-a tra le classi. Poiché la relazione is-a è transitiva (dalla sua definizione) il grafo deve essere aciclico (o meglio, se c'è un ciclo l'unica cosa che puoi concludere è che tutto in un ciclo è in realtà la stessa cosa). Molte lingue applicano ulteriori restrizioni (ad es., Forzando un albero invece di un DAG) a causa dell'esperienza con la complessità dell'ereditarietà del C ++, ma ciò non è inerente mentre la restrizione ai DAG è.

Ma ci sono altre possibili relazioni, a condizione che il requisito generale di transitività venga abbandonato. Questo è il motivo per cui la delega è un modello software così importante; è la base per molte implementazioni relazionali.

    
risposta data 07.02.2011 - 00:15
fonte
0

Il problema che ti riguarda è un problema in alcuni contesti di sviluppo (come la progettazione di giochi), e la soluzione più vicina che le persone hanno trovato sembra essere oggetti basati su componenti.

In parole povere, ti consente di aggiungere funzionalità a un oggetto aggiungendo più componenti (un po 'di tag simili) ad esso. Questa domanda su Stack Overflow esplora il problema.

    
risposta data 07.02.2011 - 00:22
fonte