Esistono lingue OO senza ereditarietà?


22

Durante una revisione del codice oggi, un mio collega ha detto qualcosa di interessante:

prototypeè utile solo quando hai bisogno dell'eredità - e quando l'eredità è sempre una buona idea ?

Ci ho pensato e mi sono reso conto che di solito uso l'ereditarietà per aggirare il codice che è stato mal progettato in primo luogo. Lo stile OO moderno preferisce la composizione rispetto all'eredità, ma non conosco alcuna lingua che lo abbia preso a cuore e che effettivamente lo imponga .

Esistono linguaggi di programmazione generici con classi, oggetti, metodi, interfacce e così via che non consentono l'eredità basata su classi? (Se un'idea del genere non ha senso, perché no?)


7
Il tuo collega ti ha portato fuori strada. È prototypeutile anche quando si hanno metodi e proprietà pubblici che devono essere condivisi tra istanze. E 'anche utile perché consente di utilizzare correttamente l' instanceofoperatore in JavaScript: if (foo instanceof Foo) { ....
Greg Burghardt,

2
Penso che dovremmo fare una distinzione tra l'eredità di tipo, stato e comportamento. La preferenza di composizione è molto comune nella comunità Java ma allo stesso tempo, l'ereditarietà (e persino l'ereditarietà multipla) dei tipi è ampiamente utilizzata e incoraggiata ... e realizzata usando la implementsparola chiave e le interfacce (al contrario dell'eredità di stato e comportamento introdotto con l'uso della extendsparola chiave su classi contenenti qualsiasi implementazione).
toniedzwiedz,

6
Preferire la composizione non significa abbandonare completamente l'eredità è una buona idea.
Caleb,

5
vedi Java senza ereditarietà dell'implementazione : "Google's go è un esempio di un linguaggio che elimina l'eredità dell'implementazione pur essendo OOP ..."
moscerino

1
@GregBurghardt Lo stesso può essere realizzato con una funzione factory che restituisce un oggetto contenente funzioni (memorizzazione di dati privati ​​nella chiusura). new, thisE prototypesono tutti troppo di un campo minato per l'uso comune IMO.
Benjamin Hodgson,

Risposte:


18

Mettendo da parte la domanda sulla definizione di programmazione orientata agli oggetti, la domanda diventa una delle "esistono lingue che usano solo la composizione e non hanno strumenti per l'ereditarietà?"

La risposta è semplicemente "sì". In atto, non c'è modo di fare l'eredità come si pensa in modo classico. Si può incorporare un oggetto in un altro oggetto ed estenderlo. Da Object Desoriented Language ( github mirror ):

type Person struct {
        Name string
}

func (p *Person) Intro() string {
        return p.Name
}

type Woman struct {
        Person
}

func (w *Woman) Intro() string {
        return "Mrs. " + w.Person.Intro()
}

Hai una persona strutt che ha un nome che è una stringa. Ha una funzione pubblica chiamata Intro che restituisce il nome. La struttura Donna ha anche una funzione per Intro che accede al puntone incorporato in essa. E così si possono realizzare le intenzioni dell'eredità usando solo la composizione.

Ulteriori informazioni al riguardo sono disponibili in Tutorial GoLang: ereditarietà e sottoclasse in Go - o nella sua somiglianza .

Quindi sì, è possibile avere un linguaggio OO senza ereditarietà e ne esiste uno.

In go go questo è noto come incorporamento e offre alle strutture che racchiudono la possibilità di accedere ai campi e alle funzioni incorporati come se li avesse anche loro - ma non è una sottoclasse. La filosofia di progettazione si trova nelle Domande frequenti su Go: Perché non esiste un'ereditarietà di tipo?


Si potrebbe anche commentare l'uso di typedefe structin C ...
cwallenpoole,

@cwallenpoole ci sono davvero idee simili lì, anche se esiterei a chiamare C un linguaggio orientato agli oggetti.

Non so. Devo ammettere che non è possibile creare oggetti con funzioni associate, ma senza ereditarietà OOP perde molto del suo sapore.
cwallenpoole,

@cwallenpoole e iniziamo a definire cos'è l'ereditarietà e l'orientamento agli oggetti. Ma è possibile, è solo un modo diverso di pensare al problema. Il fatto è che l'ereditarietà è il modo in cui la maggior parte dei programmatori C ++ e Java pensa all'estensione ... ma ci sono altri modelli. Estensione senza ereditarietà: 1 , 2 , 3 sono letture valide.

Il link a "Object Desoriented Language" è bloccato in un ciclo di reindirizzamento al momento, ma ho trovato l'articolo qui: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/… . Grazie!
Matt Browne,

7

Esistono linguaggi di programmazione generici con classi, oggetti, metodi, interfacce e così via che non consentono l'eredità basata su classi?

Questo assomiglia molto a una descrizione di VBA - Visual Basic, Applications Edition, incorporato in Microsoft Office e altri host abilitati per VBA (ad esempio AutoCAD, Sage 300 ERP, ecc.) O persino VB6. La "A" di "Base" sta per "Per tutti gli usi", quindi c'è la parte "per tutti gli usi".

VB6 / VBA ha classi (e quindi oggetti), metodi e interfacce - potresti definire ISomethingun'interfaccia in un modulo di classe come questo:

Option Explicit

Public Sub DoSomething()
End Sub

E poi avere un'altra classe che fa questo:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

Una classe del genere, che non espone membri pubblici, è sempre accessibile solo tramite la sua ISomethinginterfaccia - e potrebbero esserci ben dozzine di implementazioni diverse ISomethinglà fuori, quindi il codice VBA OOP è perfettamente in grado di polimorfismo ed è perfettamente legale per una determinata classe per implementare anche più interfacce.

VB6 / VBA non consente l' ereditarietà delle classi , quindi non è possibile ereditare un'implementazione da un altro tipo, ma solo dalla sua interfaccia. Ora, se questo è un incidente, un difetto di progettazione, un colpo di genio o un'enorme brutta supervisione è aperto al dibattito; non è chiaro se VB6 / VBA lo tenga a cuore , ma sicuramente lo impone .

Se Go non eredita la classe ed è comunque un linguaggio OOP , allora non vedo perché VB6 / VBA non possa essere considerato anche un linguaggio OOP.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>


1
Per essere onesti, OP ha chiesto delle lingue moderne . =;) -
RubberDuck,

@RubberDuck #burn!
Mathieu Guindon,

0

È possibile fare in modo che il compilatore imponga l'ereditarietà selettiva attraverso l'uso di privato / protetto e attraverso l'uso moderno delle tecniche "PImpl" o "Implementazione privata".

Molte API espongono solo quei componenti che vorresti che un utente ereditasse e nascondono il resto in una classe di implementazione separata. Quindi potresti scrivere classi le cui interfacce pubbliche sono, in effetti, non ereditabili, utilizzabili solo attraverso la composizione degli oggetti e applicate dal compilatore. Questa è spesso una buona pratica, quando utilizza il compilatore per imporre l'intento del software.

Una rapida ricerca delle funzioni di membri privati ​​in JavaScript mostra che esiste un principio simile, sebbene chiunque possa vedere il tuo codice se può usarlo: http://www.crockford.com/javascript/private.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.