View Full Version : [PHP] Oggetti: chiarimenti su abstract e interfacce
Matrixbob
24-07-2010, 14:16
Ho capito che ci possono essere classi e medodi di classi astratti.
Astrarre metodi in una classe serve a imporre al programmatore una loro implementazione specifica a seconda del caso qualora si voglia riutilizzare quella determinata classe. Giusto?
Ma una classe astratta invece a che serve?
<?PHP
echo "<br><br>- bob: prova di astrazioni -<br>";
abstract class Foo{
abstract function toString();
abstract function version();
}
class Bar extends Foo{
function toString(){
print "toString exe<br>";
return 'Class:Bar';
}
function version(){
print "version exe<br>";
return 'classe derivata';
}
}
$bar = new Bar();
$bar->toString();
$bar->version();
?>
Le interfacce servono invece ad aggirare il problema della NON multi-ereditarietà?
<?PHP
echo '<br><br>- bob: prova di interfacce -<br>';
// servono a garantire che certe classi,
// a cui saranno applicati determinati metodi,
// rispettino dei requistiti
interface Foo2{
function price();
}
class Bar2 implements Foo2{
function price(){
print 'price exe<br>';
return 99;
}
}
$b = new Bar2();
$b->price();
echo '<br><br>- bob: prova di ereditarietà multipla -<br>';
interface Foo3{
function price();
}
interface Bar3{
function name();
}
class FooBar implements Foo3, Bar3{
function price(){
return 99;
}
function name(){
return 'boh<br>';
}
}
$fb = new FooBar();
if ($fb instanceof Foo3){
echo '$fb is a Foo3 object<br>';
}
if ($fb instanceof Bar3){
echo '$fb is a Bar3 object<br>';
}
if ($fb instanceof FooBar){
echo '$fb is a FooBar object<br>';
}
echo $fb->name();
echo $fb->price();
?>
Matrixbob
24-07-2010, 14:19
Ovviamente sono ancora un po' confuso, se saprete aiutarmi a fare chiarezza ve ne sarò grato!
allora una classe astratta ti serve per definire una sorta di tassonomia delle tue classi, in questa maniera hai il vantaggio di definire particolari proprietà comuni ed inoltre sfrutti il principio d'inclusione proprio della programmazione OO: metodi che lavorano su tale classe astratta accetteranno per poliformismo anche istanze di classi derivate.. (una istanza di classe B che estende una classe A è (anche) una istanza di classe A)
le interfacce invece si utilizzano proprio per quello che tu giustamente dici, a garantire particolari vincoli e che particolari metodi siano implementati e anche esattamente per tutti quei linguaggi in cui la ereditarietà multipla non è (giustamente) supportata (vedi Java) ma la implementazione multipla si.
Possiamo anche dire, in altre parole, che un' interfaccia è una classe astratta in cui tutti i metodi siano astratti e che non dispone di attributi non inizializzati
anonimizzato
24-07-2010, 18:00
Direi che cdere ha spiegato molto bene i concetti. ;)
Anch'io avevo poco chiara l'utilità delle interfacce finchè in un progetto recente in Java (J2EE) non ho avuto a che fare con "service layer" e "Dao layer".
Matrixbob
24-07-2010, 20:19
Direi che cdere ha spiegato molto bene i concetti. ;)
Anch'io avevo poco chiara l'utilità delle interfacce finchè in un progetto recente in Java (J2EE) non ho avuto a che fare con "service layer" e "Dao layer".
Infatti, volevo chiedervi se avevate degli esempi veritieri vostri, di casi reali, o anche degli snip di vostri lavori perchè non so se quello che ho tirato fuori io abbia tanto senso. :)
Matrixbob
28-07-2010, 16:37
le interfacce invece si utilizzano proprio per quello che tu giustamente dici, a garantire particolari vincoli e che particolari metodi siano implementati e anche esattamente per tutti quei linguaggi in cui la ereditarietà multipla non è (giustamente) supportata (vedi Java) ma la implementazione multipla si.
Prof. quindi in realtà stiamo parlando di implementazione multipla e non ereditarietà multipla, c'è qualche differenza o si equivalgono?
Prof. quindi in realtà stiamo parlando di implementazione multipla e non ereditarietà multipla, c'è qualche differenza o si equivalgono?
no ma quale prof. ma va :D
Bhè le differenze ci sono e sono conseguenze dirette dei concetti stessi di ereditarietà e implementazione.
Un'interfaccia specifica solo quali servizi una classe (o un'altra interfaccia) che implementa tale interfaccia DEVE implementare ed esportare (nell'implementazione di interfaccia la visibilità degli attributi/metodi deve rimanere invariata).
Quindi una classe A può implementare le interfacce B e C, quindi l'interfaccia di A esporrà sicuramente i servizi di B, sicuramente i servizi di C e, se ce ne sono, i servizi di A stessa. Questo è possibile perchè comunque non può esserci un conflitto d'implementazione, nel caso di ereditarietà multipla infatti se B dispone di un metodo stampa() che stampa: "ciao", e C dispone di un metodo stampa() che stampa "addio", se A ereditasse sia da B che da C (caso possibile in C++) e un oggetto istanza di A invocherebbe stampa() che stringa verrebbe stampata?
E' bene non confondere i due concetti di ereditarietà e di interfaccia, ad una prima occhiata superficiale potrebbero sembrare molto simili, ma sono semanticamente 2 mondi opposti
Matrixbob
20-09-2010, 14:21
Rieccomi a tornare sull'argomento restato in sospeso, sperando di chiarimi le idee una volta per tutte.
Riprendo il primo 3D da
Ho capito che ci possono essere classi e medodi di classi astratti.
Astrarre metodi in una classe serve a imporre al programmatore una loro implementazione specifica a seconda del caso qualora si voglia riutilizzare quella determinata classe. Giusto?
Ma una classe astratta invece a che serve?
.. e vado a commentare quanto il buon cdere ha enunciato.
una classe astratta ti serve per definire una sorta di tassonomia delle tue classi, in questa maniera hai il vantaggio di definire particolari proprietà comuni ed inoltre sfrutti il principio d'inclusione proprio della programmazione OO: metodi che lavorano su tale classe astratta accetteranno per poliformismo anche istanze di classi derivate.. (una istanza di classe B che estende una classe A è (anche) una istanza di classe A)
Tassonomia nel senso di "ordine di regole" / "classificazione di concetti"?
Quindi (io per capire devo andare terra terra con degli esempi esaustivi) è il caso di una fantomatica classe "FiguraGeometrica" che ha i metodi "Perimetro" e "Area" astratti perchè le classi "Triangolo" e "Cerchio" che la estenderanno andranno a definire specificatamente gli algoritmi corretti per quelle figure in quei metodi?
Un'interfaccia specifica solo quali servizi una classe (o un'altra interfaccia) che implementa tale interfaccia DEVE implementare ed esportare (nell'implementazione di interfaccia la visibilità degli attributi/metodi DEVE rimanere invariata).
Quindi una classe A può implementare le interfacce B e C, quindi l'interfaccia di A esporrà sicuramente i servizi di B, sicuramente i servizi di C e, se ce ne sono, i servizi di A stessa. Questo è possibile perchè comunque non può esserci un conflitto d'implementazione, nel caso di ereditarietà multipla infatti se B dispone di un metodo stampa() che stampa: "ciao", e C dispone di un metodo stampa() che stampa "addio", se A ereditasse sia da B che da C (caso possibile in C++) e un oggetto istanza di A invocherebbe stampa() che stringa verrebbe stampata?
E' bene non confondere i due concetti di ereditarietà e di interfaccia, ad una prima occhiata superficiale potrebbero sembrare molto simili, ma sono semanticamente 2 mondi opposti.
Quindi a me sembra che la multiereditarietà sia lasciata all'automatismo del sistema, mentre la multiimplementazione al volere del programmatore?
Matrixbob
20-09-2010, 14:44
Interessante
Diamond problem [IT] (http://it.wikipedia.org/wiki/Diamond_problem)
Diamond problem [EN] (http://en.wikipedia.org/wiki/Diamond_problem)
Spero che tu abbia conservato l'intuizione originale (hey, 'ste due cose mi sembrano la stessa) perchè è quella corretta.
La spiegazione non è complicata ma, direi, articolata. In verità è tripartita. Occorrerebbe in effetti fare un discorso storico, uno che riguarda gli effetti "meccanici", ed uno teorico.
La storia ci direbbe perchè esistono linguaggi che hanno le interfacce e linguaggi che hanno le classi astratte e fino a che punto coincidono.
L'effetto riguarderebbe il risvolto pratico dell'uso di una classe astratta rispetto ad un'interfaccia: una volta che le hai fatte, ci sono cose che puoi fare con una che non puoi fare con l'altra e viceversa.
La teoria, dell'orientamento agli oggetti. Ci dice invece quando scegli usare una classe astratta o un'interfaccia rispetto ad una classe non astratta.
Il problema è che la terza è strana senza le altre due. Direi quasi sorprendente, basti citare il fatto che nessuno dei concetti di classe astratta, interfaccia o ereditarietà è autonomo rispetto ai fondamenti dell'orientamento agli oggetti (i primi due sono casi di definizioni, il secondo è una forma di composizione).
Quindi, se vuoi essere lungamente annoiato, fai un fischio. Ti avviso però che l'entità del polpettone da buttar giù è considerevole.
Matrixbob
20-09-2010, 17:15
Spero che tu abbia conservato l'intuizione originale (hey, 'ste due cose mi sembrano la stessa) perchè è quella corretta
.... <snip> ....
Quindi, se vuoi essere lungamente annoiato, fai un fischio. Ti avviso però che l'entità del polpettone da buttar giù è considerevole.
Diciamo che se puoi essere schematico, suntivo, pedantico ed esaustivo potremmo tutti uscirne bene e magari discutere a punto (e ti ringrazierei tanto), se invece scrivi il Manzoni ... è finita! ;)
Non per niente il titolo è "[PHP] Oggetti: chiarimenti su abstract e interfacce"
Piccola parentesi "multi ereditarietà" se pure Microzoz con C# ripiega dalla multi ereditarietà del C++ verso la multi implementazione un motivo ci sarà!
Mah, è difficile [compiere l'impresa] evitando di comporre un elenco telefonico [mentr]e mischiando tutto si rischia il classico frittatone dove a guardar bene non si dice un bel nulla. Vediamo cosa salta fuori cercando di limitare le chiacchiere.
E' noto che classi, astratte o no, e interfacce, non siano affatto espressione di mondi totalmente opposti. Esprimono invece due punti di vista di cui uno è l'ampliamento dell'altro.
Prospettiva storica.
Interfaccia = ereditarietà scandinava = i genitori passano ai figli la dichiarazione delle proprie caratterestiche, non la definizione: se papà è giallo, figlio ha un colore, quale spetta a lui dirlo.
Classe = ereditarietà americana = estensione = i genitori passano ai figli la dichiarazione e la definizione, se presente: se papà è colorato, figlio è colorato. Se papà è giallo (cioè colorato di giallo) figlio è giallo.
La ragion d'essere delle classi astratte sta nell'estesione, che è una "ereditarietà (scandinava) PIU' qualcos'altro", cioè la definizione. E' chiaro che se posso mischiare qualcosa che è dichiarato e definito a qualcosa che è solo dichiarato, il recipiente dove mescolo non possa essere che astratto: gli manca un pezzo per essere compiuto.
Il perchè dell'estensione, cioè perchè prendiamo il concetto di ereditarietà ovvero la trasmissione di un insieme di dichiarazioni e gli ficchiamo dentro anche l'eventualità che il trasporto includa una definizione, è pratico: perchè così possiamo riciclare il codice delle funzioni dichiarate nel supertipo.
E' comodo, molto comodo, abbastanza da chiedersi "se è così comodo, come mai gli scandinavi, che non erano fessi, non la volevano"?
La conseguenza della risposta è il "diamante". La risposta è:
tutti i casi di ereditarietà come trasmissione della dichiarazione di un predicato dal genitore al figlio sono definiti, non tutti i casi di ereditarietà (estensione) come trasmissione della dichiarazione e della definizione di un predicato dal genitore al figlio sono definiti e, precisamente, non sono definiti i casi in cui i genitori condividano la definizione di uno stesso predicato.
Mamma gialla, papà blu.
1) Figlio (ereditarietà scandinava): colorato
2) Figlio (estensione o ereditarietà americana): ???
Il caso 2 ha tre soluzioni, le ometto per brevità.
Questa è la storia malamente raccontata delle classi astratte. Esistono per via della definizione ante litteram di ereditarietà e della divergenza tra le due scuole citate.
La genesi spiega una marea di cose. Ad esempio come mai la massima estensione del concetto di classe astratta coincida con quello di interfaccia.
Se quaglia e non ci sono dubbi, domande o curiosità, passiamo alla questione meccanica. Quaglia?
Matrixbob
20-09-2010, 18:23
Chiaro chiaro no, stasera dopo cena spulcio.
Piccolo :ot:, voi per caso avete idea di perchè nei miei esempi ho trovato come nome di funzione FooBar? Significa qualcosa in particolare?
foo e bar/baz sono nomi d'esempio. FooBar è un mix dei due. Non ha significato.
L'ereditarieta' serve per modellare relazioni di tipo "Is Of"
mentre l'implementazione per modellare relazioni di tipo "Can Do"
L'ereditarieta' serve per modellare relazioni di tipo "Is Of"
mentre l'implementazione per modellare relazioni di tipo "Can Do"
più che altro Must Do...
L'ereditarietà serve per consentire a due pezzi di un programma di scambiarsi dati senza che ciò comporti un vincolo tra le loro definizioni.
E', cioè, una forma di composizione tra definizioni in forza della quale due oggetti (definizioni non incluse in altre definizioni, definizione = insieme nominato di predicati) condividono una stessa parte (definizione inclusa)
So che suona strana detta così ma è solo per i termini perchè il fenomeno che ci sta dietro è arcinoto e chiunque usi un linguaggio OO lo riproduce in continuazione.
E' il "separare l'interfaccia dall'implementazione", il "disaccoppiare", direi quasi anche la depency injection - ma con le pinze, non ho approfondito la questione.
C'è sempre, se ci fate caso, l'ereditarietà di mezzo. E c'è un motivo: senza il collegamento dinamico tra due tipi di dato, tra due definizion, non è possibile realizzare un sistema composto di oggetti, cioè di cose che collaborano senza perdere la propria identità.
Il fatto che sia una necessità è importante perchè se ci limitiamo a dire che serve quando vuoi dire "è un" viene da chiedersi: e qual'è la regola in base alla quale decido chi è cosa?
Matrixbob
27-09-2010, 16:44
Sicuramente avrò capito male, ma ho capito così:
http://img534.imageshack.us/img534/6210/immaginenj.png
Spero che tu abbia conservato l'intuizione originale (hey, 'ste due cose mi sembrano la stessa) perchè è quella corretta.
Quota a quale asserzione mia riferisci va! :p :)
... e al post #8 avevo capito bene? (http://www.hwupgrade.it/forum/showpost.php?p=33140936&postcount=8)
Matrixbob
27-09-2010, 16:54
L'ereditarietà serve per consentire a due pezzi di un programma di scambiarsi dati senza che ciò comporti un vincolo tra le loro definizioni.
Ok.
E' il "separare l'interfaccia dall'implementazione", il "disaccoppiare", direi quasi anche la depency injection - ma con le pinze, non ho approfondito la questione.
, questo non è espresso qui (http://www.hwupgrade.it/forum/showpost.php?p=33140936&postcount=8)?
Un'interfaccia specifica solo quali servizi una classe (o un'altra interfaccia) che implementa tale interfaccia DEVE implementare ed esportare (nell'implementazione di interfaccia la visibilità degli attributi/metodi DEVE rimanere invariata).
Quindi una classe A può implementare le interfacce B e C, quindi l'interfaccia di A esporrà sicuramente i servizi di B, sicuramente i servizi di C e, se ce ne sono, i servizi di A stessa. Questo è possibile perchè comunque non può esserci un conflitto d'implementazione, nel caso di ereditarietà multipla infatti se B dispone di un metodo stampa() che stampa: "ciao", e C dispone di un metodo stampa() che stampa "addio", se A ereditasse sia da B che da C (caso possibile in C++) e un oggetto istanza di A invocherebbe stampa() che stringa verrebbe stampata?
E' bene non confondere i due concetti di ereditarietà e di interfaccia, ad una prima occhiata superficiale potrebbero sembrare molto simili, ma sono semanticamente 2 mondi opposti.
Quindi a me sembra che la multiereditarietà sia lasciata all'automatismo del sistema, mentre la multiimplementazione al volere del programmatore?
Matrixbob
27-09-2010, 17:38
Una volta, da qualche parte, lessi che la programmazione ad oggetti si basa sulle 3 fondamenta seguenti.
Incapsulamento (Encapsulation): il processo di unire elementi per formare un nuovo elemento;
Polimorfismo (Polymorphism): la possibilità di un linguaggio di gestire gli oggetti in modo diverso in base al loro tipo;
Ereditarietà (Inheritance): la possibilità di un linguaggio di definire una classe o un oggetto come estensione di un'altra classe o di un altro oggetto.
Queste 3, confermate?
L'intuizione corretta a cui mi riferivo era il dubbio (che mi è sembrato di cogliere) che interfacce e classi astratte fossero "la stessa cosa" (da un punto di vista generale).
La programmazione orientata agli oggetti non è fondata su quelle tre cose.
In effetti delle tre solo la terza è tipica ma non come principio.
L'incapsulamento è proprio della programmazione modulare (da C in su), il polimorfismo attiene alla teoria dei tipi (che vale a partire dal linguaggio macchina).
La fola nasce da una pubblicazione di Strostrup di mille anni fai in cui egli spiegava cosa avesse ritenuto essere orientato agli oggetti ai fini dell'implementazione di C++ (se fai una ricerca con "stroustrup, object oriented, c++" potresti trovarlo).
Circa l'ereditarietà essa è presente in tutti in linguaggi OO ma solo come strumento, come "utilità pratica" che realizza quel particolare schema di condivisione che permette a due oggetti di comunicare senza che uno assorba l'altro.
Il fondamento dell'orientamento agli oggetti è un principio che si chiama princpio di identità secondo il quale in tanto un elemento di un sistema è identificabile in quanto possieda almeno una caratteristica in via esclusiva.
Quegli elementi identificabili sono gli oggetti.
Lì inizia e finisce la storia dell'orientamento agli oggetti. Io ogni tanto cito per amor di patria disaccoppiamento, interfacce, classi e via dicendo ma a rigore sono tutte chiacchiere per menti annebbiate.
Matrixbob
27-09-2010, 18:49
Lì inizia e finisce la storia dell'orientamento agli oggetti. Io ogni tanto cito per amor di patria disaccoppiamento, interfacce, classi e via dicendo ma a rigore sono tutte chiacchiere per menti annebbiate.
Eh e che ti devo dì se ho aperto il 3D era x svelare le oscure nebbie.
Forse essere nati prima e aver vissuto la trafila non avrebbe lasciato incertezze. :boh:
Ma non sei tu la mente annebbiata a cui mi riferisco. Tu dovresti vedere che segoni si fanno certi quando parlano di orientamento agli oggetti.
Alla fine della fiera a te delle classi astratte/interfacce interessa che:
1. PHP le ha. Ci sono lingue che non hanno nè le une nè le altre (es. Scala) eppure sono perfettamente "orientate agli oggetti"
2. tutte e due ti permettono di "ereditare", cioè di collegare la definizione di un tipo alla definizione di un altro tipo
3. con le classi astratte puoi "spostare" dei pezzi di codice, dal supertipo al sottotipo.
Vale a dire, ti interessa l'insieme di effetti che PHP associa a classi astratte o interfacce.
Ti interessano solo gli effetti pratici e non la teoria perchè non c'è una teoria dietro, c'è solo una storia.
Matrixbob
27-09-2010, 19:28
Ma non sei tu la mente annebbiata a cui mi riferisco. Tu dovresti vedere che segoni si fanno certi quando parlano di orientamento agli oggetti.
Alla fine della fiera a te delle classi astratte/interfacce interessa che:
1. PHP le ha. Ci sono lingue che non hanno nè le une nè le altre (es. Scala) eppure sono perfettamente "orientate agli oggetti"
2. tutte e due ti permettono di "ereditare", cioè di collegare la definizione di un tipo alla definizione di un altro tipo
3. con le classi astratte puoi "spostare" dei pezzi di codice, dal supertipo al sottotipo.
Vale a dire, ti interessa l'insieme di effetti che PHP associa a classi astratte o interfacce.
Ti interessano solo gli effetti pratici e non la teoria perchè non c'è una teoria dietro, c'è solo una storia.
Alleluia fratello!
banryu79
28-09-2010, 08:59
Ti interessano solo gli effetti pratici e non la teoria perchè non c'è una teoria dietro, c'è solo una storia.
Questa è da firma :asd:
Matrixbob
21-10-2010, 09:53
Cacchio mi è venuto un dubbio, la implementazione multipla è quello che si chiama polimofismo? :stordita: :fagiano:
Cacchio mi è venuto un dubbio, la implementazione multipla è quello che si chiama polimofismo? :stordita: :fagiano:
Piu' semplcimente l'ereditarieta', anche senza la derivazione di una classe da 2 classi.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.