C'è già una bella risposta, ma ho notato questa parte:
I might think of Interface as just multiple inheritance, but just that
we don't want to have the issues of multiple inheritance [...]
Immagino che tu stia lavorando in una lingua in cui la nozione di "interfaccia" è rigorosamente priva di status. Trovo spesso quelli in qualche modo pesanti e penso che l'ereditarietà multipla non sia così disordinata come alcuni lo fanno sembrare.
Tuttavia, a livello concettuale, l'interfaccia stateless è spesso la più generale, la più ideale dal punto di vista contrattuale e di manutenzione.
Robot con ruote
Ad esempio, immagina di aver scritto una barca di codice usando un'interfaccia robotica che comandava ai robot di andare in vari luoghi (stanze, edifici, paesi).
Se detta interfaccia includesse attributi come l'idea che un robot abbia ruote, ciò accoppiasse le mie richieste all'idea che un robot abbia ruote. Le mie richieste sarebbero quindi valide solo per i robot dotati di ruote (potrebbero comunque essere in grado di andare in nuove posizioni usando altri mezzi di trasporto, ma almeno richiedono possedere ruote per farlo) > p>
Che degenera il concetto di robot a chi possiede almeno ruote e allo stesso modo degeneralizza tutte le richieste che ho fatto per i robot di andare in posti nuovi che potrebbero estendersi su decine di migliaia di linee di codice, ad es.
Ora diciamo che è stato introdotto un nuovo robot che ha gambe, o un jetpack, o un trasportatore molecolare e in realtà non aveva affatto bisogno di ruote. Questo crea problemi per tutte le classi di robot esistenti e tutti i codici esistenti che li utilizzano attraverso questa interfaccia. Ora siamo in una posizione piuttosto scomoda di dover riscrivere un sacco di codice che non saremmo in se l'interfaccia / contratto per i robot fosse senza stato.
Le interfacce flessibili consentono varietà
In generale, le interfacce più ideali dal punto di vista dell'uscita del codice che è resiliente al cambiamento lasceranno molto spazio a una ricca varietà di implementazioni concrete senza violare il contratto dell'interfaccia. Una volta che lo stato viene introdotto in un'interfaccia, spesso degrada molto rapidamente la ricchezza e può ridurre significativamente la varietà di possibili soluzioni.
Questo dovrebbe essere forzato in modo assoluto in una progettazione linguistica? Non lo so - sono prevenuto come uno che preferisce le lingue che non lo forzano. Tuttavia, penso che sia generalmente molto meglio se commettiamo errori verso interfacce senza stato. Un attributo / stato molto più rapidamente degraderà la generalità delle tue astrazioni rispetto alle funzioni.
But interface is only about methods, then how would we think about
adding attributes to the class due to interface?
Questi sono problemi di implementazione. Se l'obiettivo di una classe che implementa un'interfaccia Movable
è di spostarsi in nuove posizioni, è possibile implementare tutti i tipi di metodi e rappresentare anche i dati necessari per farlo. Cerca di apprezzare questa flessibilità / libertà.
Probabilmente una preoccupazione qui è che, dopo la dozzina di classe o giù di lì, ti sembra di duplicare molto lo stesso tipo di piastra per implementare un'interfaccia. In tal caso, puoi raggiungere potenzialmente una classe base astratta, o usare la composizione (memorizzare un membro che fa un sacco di gruntwork), possibilmente metodi statici (forse la più grossolana, comunque, se inizia ad assomigliare a una funzionalità di helper anonimo) , ecc.
Ma prova a tenere a mente quanto sia flessibile l'interfaccia in quanto è stateless, di non menzionare dettagli concreti come parte del suo contratto.