Abstract vs Interface

di il
4 risposte

Abstract vs Interface

Che differenza c'è tra queste due strutture:

1a struttura

interface ICombatti { void combatti(); }

interface IAzzanna { void azzanna(); }

abstract class Personaggio

{

    proprietà comuni Forza e Nome implementate……

}

class Eroe: Personaggio, ICombatti

{

public void combatti(){ ……}

}

class Vampiro: Personaggio, IAzzanna

{

public void azzanna(){ ……}

}

class Licantropo: Personaggio, IAzzanna, ICombatti

{

}

2a struttura

interface IPersonaggio { proprietà forza e nome non implementate}

interface ICombatti: IPersonaggio { void combatti(); }

interface IAzzanna: IPersonaggio { void azzanna(); }

class Eroe: ICombatti{

proprietà forza e nome implementate

public void combatti(){ ……}

}

class Vampiro: IAzzanna{

proprietà forza e nome implementate

public void azzanna(){ ……}

}

class Licantropo: ICombatti, IAzzanna{

proprietà forza e nome implementate

public void combatti(){ ……}

public void azzanna(){ ……}

}

4 Risposte

  • Re: Abstract vs Interface

    Al netto del fatto che il codice dovrebbe essere formattato per essere leggibile correttamente, spiegazioni su cosa sono le interfacce e le classi astratte le trovi ovunque, da cui poi ti sarà possibile ricavarne anche le differenze.

    Un conto è leggere qualcosa e aver bisogno di chiarimenti, ma non è questo il caso, un conto invece è pubblicare uno stralcio di codice malformattato e farselo spiegare.

    Ad esempio, ne parla questo articolo (il linguaggio è Java, ma i concetti sono gli stessi).

    Documentati prima, poi analizza il codice e se hai bisogno di aiuto, spiega i tuoi dubbi, senza delegare l'onere dell'intero esercizio agli altri.

  • Re: Abstract vs Interface

    31/05/2023 - zoro82 ha scritto:


    Ma guarda, io non volevo spiegazioni. So la differenza tra un'interfaccia e una classe astratta. 

    Infatti quello che volevi non era affatto chiaro, e ciò che si poteva supporre con la scarsità delle indicazioni fornite in realtà non era esattamente quello che ti interessava. Definire bene le domande richiede tempo, ma almeno lo fa risparmiare a chi eventualmente vuole rispondere, evitando di commentare quello che non è necessario senza magari risolvere il dubbio reale.

    31/05/2023 - zoro82 ha scritto:


    Il problema è che le ultime versioni di C# consentono di inserire nelle interfacce anche le proprietà snaturandone quella che è la natura originaria

    Che io sappia, le proprietà nelle interfacce esistono già da parecchie versioni di C#.

    Le proprietà non vanno a snaturare la natura dell'interfaccia, se sai cosa sono le proprietà e come sono implementate in .NET (vedi la documentazione ufficiale).

    31/05/2023 - zoro82 ha scritto:


    io ho imparato che la classe è il contentitore di dati, l'interfaccia è un contenitore di metodi comuni che si usa per non portarsi dietro tutto il fardello dell'ereditarietà

    Infatti le proprietà non sono un “contenitore” di dati: quelli sono i campi. Prova a inserire un campo in una interfaccia, e vedrai che quanto dici rimane verificato.

    Quello che indichi tu è solo uno degli utilizzi più comuni, ma non sono definizioni proprie delle classi astratte e delle interfacce.

    In linea più generale, le interfacce potrebbero essere definite come un “contratto”, mentre le classi (che siano astratte o no) sono una implementazione reale di quel “contratto” (se implementano una interfaccia).

    La caratteristica di essere “astratta” delinea solo l'impossibilità di implementare un metodo in una classe perché il livello che essa rappresenta nella gerarchia è tale per cui si è consapevoli che quella funzionalità è comune a tutti i discendenti, che ciascuno di essi la implementa in modo diverso, ma che nel “fattore comune” non è possibile indicare una implementazione valida (rappresenta appunto un concetto astratto).

    31/05/2023 - zoro82 ha scritto:


    Tuttavia, il fatto di poter avere delle interfacce che derivano da altre interfacce e poter mettere nella interfaccia madre delle proprietà …. mi crea dei dubbi e in alcuni casi l'uso delle due soluzioni è indifferente.

    Derivare interfacce da interfacce è una comodità per evitare ripetizioni su contratti che sono estensioni di altri.

    La questione delle proprietà - ripeto - sapendo cosa sono (vedi approfondimento sopra) non dovrebbe dare luogo ad alcun dubbio.

    In alcuni casi è vero che più soluzioni possono essere indifferenti: ciò non significa che lo siano sempre, o che possano non esserlo in futuro.

    31/05/2023 - zoro82 ha scritto:


    Io infatti potrei dichiarare una <Personaggio> lista o una <IPersonaggi> lista senza che vi sia, in alcuni casi, una grossa differenza.

    Dipende, ovviamente. E' un po' come se io dicessi che, dovendo mangiare frutta per la dieta, una mela o un kiwi sono grossomodo equivalenti. Nel contesto che intendo io, lo sono, ma in generale nessuno direbbe mai che una mela è uguale a un kiwi in senso assoluto.

    Nel tuo caso infatti, il nome dell'interfaccia IPersonaggio, già denota un uso errato della stessa, in quanto essa dovrebbe definire un contratto comportamentale di ciò che il personaggio deve fare, quindi in genere l'interfaccia esprime come nome una capacità, una interazione, una azione (vedi IDisposable, ICloneable)… il fatto di usare un sostantivo (Personaggio) vuol dire che una interfaccia non serve, o che è stata creata in modo errato (ossia si è usata una interfaccia impropriamente).

  • Re: Abstract vs Interface

    Io faccio riferimento a questo esempio che gira in rete con annessa soluzione (diagramma UML): https://ibb.co/2hkW9Cm

    Secondo il mio modesto parere, l'uso dell'interfaccia Personaggio per gestire la Forza è inutile e fuorviante. Io avrei fatto solo le interfacce ICombatti e IAzzanna (per sfruttare l'ereditarietà multipla in Licantropo). Avrei fatto poi una classe astratta Personaggio con implementata la Forza (intendo con i getter e i setter) e poi avrei fatto le singole classi derivate (implementanti le giuste interfacce) in cui avrei implementato i metodi azzanna, combatti o entrambi. Infine, avrei fatto una List <Personaggio> lista

    Tuttavia, anche la soluzione proposta funziona (intendo senza l'uso di una classe astratta)  e mantiene anche l'obbligo di implementare la Forza e i vari metodi per le classi che estendono le interfacce (Qui avrei potuto fare una List <IPersonaggio> lista). L'effetto collaterale è che avrei perso la natura dell'ereditarietà, perchè avrei dovuto implementare in tutte le classi codice che avrei potuto mettere nella superclasse.

    Detto questo, cercavo di trovare un senso logico alla soluzione proposta.

  • Re: Abstract vs Interface

    31/05/2023 - zoro82 ha scritto:


    Io faccio riferimento a questo esempio che gira in rete con annessa soluzione […]

    Ho visto il diagramma e lo trovo poco… esemplificativo. Cioè, intendo dire che ci sono esempi molto migliori di scenari in cui l'uso di interfacce e classi astratte ha una valenza diversa, mentre in questo caso - per come è stata pensata la gerarchia - sono totalmente ininfluenti.

    Voglio dire che avrebbe potuto usare classi astratte e basta.

    E' anche fuorviante, perché ad esempio nella mia testa Licantropo non è assolutamente un Umano: certo, entrambi possono combattere, così come un umano può “mordere” a modo suo, usando i denti come il vampiro, oppure azzannare.

    L'esempio sarebbe stato appunto più corretto se le interfacce fossero state ICanFight o ICanByte, ovvero orientate alle azioni (vedi mio commento precedente): in quel caso, la gerarchia rispetta solo ciò che gli “attori”, che siano concretizzabili o concettuali (astratti), ereditano dalle famiglie che li accomunano in termini di implementazione, mentre - ad esempio - la possibilità di ricevere un morso da un personaggio qualsiasi sarebbe dipeso dal fatto che tale personaggio - che sia umano, licantropo, vampiro o demone incallito - implementi o meno l'interfaccia ICanByte.

    31/05/2023 - zoro82 ha scritto:


    Tuttavia, anche la soluzione proposta funziona […]

    Anche usando procedure e funzioni statiche avrebbe funzionato, ma un conto è il funzionamento, un conto è l'architettura del software che si vuole utilizzare.

Devi accedere o registrarti per scrivere nel forum
4 risposte