Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1

    Interfacce e classi astratte

    Buongiorno a tutti,

    vorrei porvi questa domanda che per molti di voi sicuramente è una fesseria, ma che per me è un qualcosa di veramente difficile da poter capire.

    In sostanza, a cosa servono queste interfacce e classi astrattte nella oop, se bisogna riscrivere il codice per ogni metodo dichiarato?

    Vi giuro, tra leggere sui libri e su internet non sto venendo a capo della loro utilità; nemmeno nel vedere demo a destra e a manca ci ho capito molto

    Spero che almeno voi possiate aiutarmi nel capire, ve ne sarei grato

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Vediamo se un parallelo aiuta a dissipare i dubbi.
    Considera un veicolo generale: hai un volante e tre pedali con cui azionarlo. Ora che tu stia guidando un'auto, un camion o un trattore, devi sempre girare un volante e schiacciare tre pedali per controllarlo.
    Pertanto le tue azioni si rivolgono a un'interfaccia astratta (volante più pedali) che controlla un mezzo concreto, di cui, in linea teorica, a te non interessa nulla di come sia il meccanismo concreto di controllo.
    Ad esempio un'auto può implementare un volante basato su idroguida, un trattore invece avrà una cremagliera, ma per sterzare devi sempre girare un volante.

    Allo stesso modo in oop un'interfaccia astratta può avere diverse implementazioni in base a una specializzazione concreta, ma che il programma non ha bisogno di sapere perché si limiterà a richiamare i metodi dell'interfaccia.
    Ad esempio se la tua interfaccia implementa i metodi sterza_a_destra e sterza_a_sinistra il programma sa che invocando tali metodi andrà a destra o sinistra, ma non ha bisogno di sapere se ciò che permette al volante di sterzare è una idroguida o una cremagliera.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Originariamente inviato da shodan
    Ad esempio se la tua interfaccia implementa i metodi sterza_a_destra e sterza_a_sinistra il programma sa che invocando tali metodi andrà a destra o sinistra, ma non ha bisogno di sapere se ciò che permette al volante di sterzare è una idroguida o una cremagliera.
    Ok, fin qui ero arrivato. Ma la domanda che mi pongo è perchè dichiarare queste interfacce se i metodi invocati avranno una codifica differente gli uni dagli altri. E' chiaro che lo sterza_a_sinistra dell'idroguida avrà un codice differente dallo sterza_a_sinistra della cremagliera, o mi sbaglio?

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da Media7
    Ok, fin qui ero arrivato. Ma la domanda che mi pongo è perchè dichiarare queste interfacce se i metodi invocati avranno una codifica differente gli uni dagli altri. E' chiaro che lo sterza_a_sinistra dell'idroguida avrà un codice differente dallo sterza_a_sinistra della cremagliera, o mi sbaglio?
    Sì, ma chi effettua la sterzata non ha bisogno di sapere concretamente chi è che deve sterzare (se l'auto o il trattore).
    Io posso avere tranquillamente una funzione che prende in ingresso un "veicolo sterzante" (di qualunque tipo esso sia), e chiamare tali metodi. Ora, poco importa che io a questa funzione gli passi un trattore o un'automobile, a me basta che effettui la sterzata. E per farlo, devo fare in modo che tale funzione accetti qualunque tipo di veicolo che sia in grado di sterzare. Come si può definire una cosa del genere? Mediante, appunto, un'interfaccia.
    Al posto di avere una funzione per il trattore e una funzione per l'automobile, avrò un'unica funzione che accetta un "veicolo sterzante", ovvero un qualunque oggetto che implementa tale interfaccia.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  5. #5
    Originariamente inviato da LeleFT
    Al posto di avere una funzione per il trattore e una funzione per l'automobile, avrò un'unica funzione che accetta un "veicolo sterzante", ovvero un qualunque oggetto che implementa tale interfaccia.
    Guarda ti prego di compatirmi ( ho come la sensazione che non sono tagliato per la programmazione ad oggetti ) ma non ne vengo lo stesso a capo: io ho una sola funzione, che deve essere dichiarata nelle classi che implementano l'interfaccia, giusto?

    Ma a che pro serve ciò se le classi che implementano questa interfaccia avranno la stessa funzione, ma con metodiche diverse?

    Voglio dire se $t è il trattore e $a è l'automobile, cosa aiuta l'interfaccia nel fare $t->sterza_a_destra() e $a->sterza_a_destra(), avendo entrambe le funzioni dei processi diversi? Non vedo nessuna utilità

  6. #6
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802
    Leggi il mio ultimo intervento qui, può esserti d'aiuto..
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  7. #7
    L'implementazione specifica sarà diversa, ma il concetto che viene implementato dev'essere lo stesso, se no ovviamente non ha senso. Ad esempio, immaginati una gerarchia di classi per cifrare dei dati: avrai una classe base astratta (AlgoritmoCifratura) con i metodi Cifra e Decifra, e delle classi derivate che implementano gli specifici algoritmi di cifratura.
    Quando hai un metodo che deve lavorare con dei dati cifrati (che so, SalvaFile), questo riceverà tra i parametri un generico oggetto di tipo AlgoritmoCifratura; il chiamante gli passerà caso per caso l'algoritmo di cifratura scelto da usare, ma per quanto riguarda SalvaFile tutto ciò che gli importa è ricevere un generico AlgoritmoCifratura di cui usare i metodi Cifra e Decifra.

    (poi nella realtà le cose potrebbero essere leggermente più complicate, ma questo era giusto per dare l'idea )
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da Media7
    Guarda ti prego di compatirmi ( ho come la sensazione che non sono tagliato per la programmazione ad oggetti ) ma non ne vengo lo stesso a capo: io ho una sola funzione, che deve essere dichiarata nelle classi che implementano l'interfaccia, giusto?

    Ma a che pro serve ciò se le classi che implementano questa interfaccia avranno la stessa funzione, ma con metodiche diverse?

    Voglio dire se $t è il trattore e $a è l'automobile, cosa aiuta l'interfaccia nel fare $t->sterza_a_destra() e $a->sterza_a_destra(), avendo entrambe le funzioni dei processi diversi? Non vedo nessuna utilità
    Mi sa che devi rileggere bene bene il mio precedente post.
    Hai un'interfaccia che chiamerò VeicoloSterzante
    Hai quattro classi: Automobile, Trattore, Triciclo, Aereo. Tutte implementano l'interfaccia VeicoloSterzante.

    Ora ho bisogno di una funzione che, dato un oggetto X (che può essere un Automobile o un Trattore o un Triciclo o un Aereo) faccia in modo che questo oggetto sterzi verso destra.

    Se non avessi l'interfaccia dovrei per forza creare 4 metodi:
    codice:
    sterzaAutomobile(Automobile x) { x.sterza_destra(); }
    sterzaTrattore(Trattore x) { x.sterza_destra(); }
    sterzaTriciclo(Triciclo x) { x.sterza_destra(); }
    sterzaAereo(Aereo x) { x.sterza_destra(); }
    Potrei anche avere lo stesso nome per il metodo, ma dovrei comunque farne l'overload per 4 volte, poichè un oggetto Automobile è diverso da un oggetto Trattore, ecc. eppure, guarda caso, il nome del metodo da richiamare sull'oggetto è sempre lo stesso: non ti sembra un po' uno spreco di tempo star lì a scrivere 4 volte la stessa cosa?

    Ma se ho l'interfaccia VeicoloSterzante...
    codice:
    sterzaVeicolo(VeicoloSterzante x) { x.sterza_destra(); }
    Punto. Qualunque sia il mio veicolo lo posso passare al metoto "sterzaVeicolo()". Ho scritto un solo metodo, una sola volta e posso passargli qualunque oggetto che implementa "VeicoloSterzante", anche oggetti che nel mio programma non sono contemplati (supponi che io stia scrivendo una libreria: qualunque programmatore che usa la mia libreria può scrivere la propria classe e farle implementare l'interfaccia Automobile... non posso né sapere come si chiamerà tale classe, né sapere quante ne programmerà, ma a me non interessa).

    E' più chiaro ora?


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  9. #9
    Originariamente inviato da LeleFT
    Mi sa che devi rileggere bene bene il mio precedente post.
    Ti chiedo di scusarmi, ma sto davvero messo male nel capire queste tecniche

    Originariamente inviato da LeleFT
    non ti sembra un po' uno spreco di tempo star lì a scrivere 4 volte la stessa cosa?
    Guarda, non so quale linguaggio tu abbia usato come riferimento, ma in php la funzione deve essere dichiarata e implementata 4 volte ( prendendo le tue classi come riferimento ).

    Quindi se tutto deve essere scritto per 4 volte, anche passando un oggetto VeicoloSterzante alla funzione, dov'è il vantaggio? Tanto vale passare l'oggetto specifico, no?

    Io credevo che l'interfaccia potesse, con una sola funzione, svolgere i processi delle classi che le implementano, ovvero un solo processo per N classi; ma se ogni classe deve implementare la sua funzione, seppur con lo stesso nome, io non ne vedo l'utilità.

  10. #10
    Be' ma se vieni da un linguaggio a tipizzazione dinamica come PHP si spiega tutto... In PHP a qualunque parametro puoi passare qualunque tipo, per cui, finché l'interfaccia di due classi è la medesima, risultano effettivamente intercambiabili. Il problema di questo approccio è che non c'è alcun controllo di validità delle operazioni che stai cercando di fare a compile-time, per cui, per scoprire che da qualche parte per errore viene passato un lavacastagne ad una funzione che si aspetta un'automobile devi aspettare che lo specifico percorso di codice che causa questo errore venga eseguito.

    Al contrario, in un linguaggio a tipizzazione statica (come C# o Java) i tipi dei parametri (e in generale delle variabili) sono fissati, e un tentativo di passare un argomento di tipo sbagliato genera un errore di compilazione. Tuttavia, oggetti di una classe derivata possono essere passati come oggetti della classe base (è il cosiddetto principio di sostituzione), per cui una funzione può accettare un parametro di tipo macchina_sterzante (classe che definisce qual è l'interfaccia usata per sterzare) e ricevere (e quindi usare) qualunque oggetto che implementa tale interfaccia.
    In questa maniera viene salvaguardata la correttezza della funzione nell'uso dei parametri (è garantito che riceverà un qualcosa che ha l'interfaccia di macchina_sterzante) ma viene concessa una certa flessibilità (posso passare qualunque cosa che possa sterzare).
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.