Pagina 1 di 1

[OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 12:47 pm
da Zane
Considerate questo scenario:

classe A
-titolo
-get+set titolo
-abstract
-get+set abstract


classe B
-abstract
-get+set abstract

-ordine
-get+set ordine


Come vedete nessuna delle due può ereditare dall'altra (erediterebbe anche un attributo e relativi get+set che non c'entrano).

La prima soluzione che mi viene in mente è "molto bene, ristruttiriamo!"

classe Titolo
-titolo
-get+set titolo

classe Abstract
abstract
-get+set abstract

classe Ordine
-ordine
-get+set ordine

classe A extends Titolo, Abstract

classe B extends Abstract, Ordine


Piccolo problema: PHP (come Java, ma al contrario del C++) non supporta l'ereditarietà multipla delle classi (ma lo supporta per le interfacce: e qui un bel "maiiial, stra-utile!!" non ce lo toglie nessuno...).

Avete qualche suggerimento su come risolvere la situazione?

Vi dico a cosa avevo pensato:

* fare dei "pezzi di codice" (tipo "titolo.php") quindi usare require. Peccato che si può fare solo a livello di metodo, e non buttata lì dentro la classe.
* Usare l'ereditarietà al contrario: fare una megaclasse astratta che implementi TUTTE le funzionalità, e quindi creare classi che estendano quella, overlodando con throw new NotImplementedException() le cose che non mi servono. Sinceramente però non mi sembra Buona Programmazione..

A voi la parola..

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 12:55 pm
da Robby78
Zane ha scritto:.... Sinceramente però non mi sembra Buona Programmazione..


...e mi sembra pure off topic, visto che hai taggato il topic come OOP! [:D]

per il momento non mi viene in mente nulla comunque... [boh]

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 1:05 pm
da M@ttia
Robby78 ha scritto:...e mi sembra pure off topic, visto che hai taggato il topic come OOP! [:D]
[?]

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 1:07 pm
da Mr.TFM
Robby78 ha scritto:per il momento non mi viene in mente nulla comunque... [boh]
Uahahahah! Non dirlo a me! [rotolo]

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 1:16 pm
da Robby78
M@ttia ha scritto:
Robby78 ha scritto:...e mi sembra pure off topic, visto che hai taggato il topic come OOP! [:D]
[?]


no beh, era una battuta scadente e un po' forzata: è che fare "megaclasse astratta che implementi TUTTE le funzionalità" è l'antitesi dell'OOP; tuttavia al momento è l'unica soluzione possibile conosciuta

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 1:21 pm
da Zane
Robby78 ha scritto:è che fare "megaclasse astratta che implementi TUTTE le funzionalità" è l'antitesi dell'OOP

Sono estremamente d'accordo. E' proprio il genere di cose che voglio evitare.

L'unica altra alternativa che vedo è "copia-incollare" i metodi comuni in tutte le classi: ma se, come ho già fatto almeno 10 volte solo stamattina, aggiungo o modifico uno di essi, devo poi ri-copia-incollare... inaffrontabile, contando che alla fine dei giochi avrò una 15ina abbondante di classi da sviluppare...

MessaggioInviato: mar giu 26, 2007 1:22 pm
da Bocca
Ma le becchi tutte tu?!?!?! [:D]

[uhm] [uhm] [uhm] [uhm] [uhm] [uhm] [uhm]

La soluzione più "tattica" che mi viene in mente è quella che hai detto tu.
Usare l'ereditarietà al contrario: fare una megaclasse astratta che implementi TUTTE le funzionalità, e quindi creare classi che estendano quella, overlodando con throw new NotImplementedException() le cose che non mi servono. Sinceramente però non mi sembra Buona Programmazione..

Re: [OOP] Niente ereditarietà multipla... come risolviamo?

MessaggioInviato: mar giu 26, 2007 1:27 pm
da M@ttia
Robby78 ha scritto:
M@ttia ha scritto:
Robby78 ha scritto:...e mi sembra pure off topic, visto che hai taggato il topic come OOP! [:D]
[?]


no beh, era una battuta scadente e un po' forzata: è che fare "megaclasse astratta che implementi TUTTE le funzionalità" è l'antitesi dell'OOP; tuttavia al momento è l'unica soluzione possibile conosciuta
Ahhhh ok! [:D]

MessaggioInviato: mar giu 26, 2007 1:42 pm
da Zane
Per il momento ho tirato fuori il buon Visio è sto cercando di capire se riesco a gerarchizzare la cosa (ad esempio, difficilmente una classe dotata di abstract non avrà titolo). Resto comunque in ascolto in caso piovano suggerimenti..[/i]

MessaggioInviato: mar giu 26, 2007 3:23 pm
da Zane
Il buon Leo mi ha sevegliato dal mio consueto Power Nap post-pranzo suggerendo la soluzione.

Class Abstract
-abstract
-set+get abstract

[url]Class A[/url]
-new Abstract
-set+get abstract che richiamano e ritornano gli omonimi metodi dell'oggetto abstract.


L'Uovo di Colombo, ma non mi era venuto [:)]

Leo sostiene che così sia anche più corretto dal punto di vista concettuale: personalmente però non sono affatto d'accordo: non avendo idee migliori e trattandosi comunque di una soluzione di Buona Programmazione, attuerò sicuramente questa tattica [:)]

MessaggioInviato: mar giu 26, 2007 3:54 pm
da Leo
Zane ha scritto:Il buon Leo mi ha sevegliato dal mio consueto Power Nap post-pranzo


E' sempre un piacere poterti svegliare! Mi illumina il resto della giornata! [;)] [;)]


Leo sostiene che così sia anche più corretto dal punto di vista concettuale: personalmente però non sono affatto d'accordo


Occhio, non credo sia la soluzione più corretta in linea generale, ma più corretta in questo caso.

Ad esempio, se volessi costruire una ipotetica classe moto composta da manubrio, ruote, acceleratore e frizione, ritengo si debba costruire la classe in modo tale che manubrio, ruote, acceleratore e frizione siano istanze nella classe moto. Moto non deve ereditare da queste classi, perché è vero che bene o male otteniamo lo stesso risultato, ma non c'è nessun grado di parentela fra la moto e le ruote. Le ruote sono un pezzo della moto.
Un estensione ha senso se devi descrivere la classe "moto da corsa" in questo caso è giusto estendere moto perché si tratta di una normale moto con qualche caratteristica in più, ma stiamo parlando sempre di una moto con le stesse caratteristiche descritte precedentemente.

Analogamente quindi si può prendere la classe che devi creare. Ipotizziamo sia la classe articolo. Un articolo è caratterizzato da un titolo, un abstract e quello che ti viene in mente. Perciò titolo e abstract devono essere contenuti in articolo come istanze delle loro classi.
Titolo e abstract non hanno gradi di parentela con articolo se non per il fatto che sono oggetti che compongono un articolo.

Per questo non credo sia giusto legare titolo e abstract ad articolo mediante ereditarietà.

Ovviamente correggetemi se sbaglio!

MessaggioInviato: mar giu 26, 2007 4:28 pm
da Robby78
[prego] [prego] [prego]

MessaggioInviato: mar giu 26, 2007 4:38 pm
da Ices_Eyes
Leo ha scritto:...

In linea di massima per la moto sono d'accordo, poi per estenderla a quello che deve fare lo zane bisognerebbe conoscere l'intera gerarchia eccetera.
Io però avrei proceduto allo stesso modo di Leo, a meno che per qulche motivo non mi fosse stato più utile fare una gerarchia di abstract, partendo dlla classe vpiù generale, e specializzando le cose anche in più rami via via che si scendeva, per arrivare alla fine ad avere delle classi di implementazioni delle abstract che "estendevano" più classi...però sempre se la cosa avesse portato a qualche utilità però [:)]

MessaggioInviato: mar giu 26, 2007 7:39 pm
da Zane
Circa l'esempio della moto sono sicuramente d'accordo, ma qui a mio modesto avviso non è la stessa cosa: provo a illustrarti il mio punto di vista.

"Ruota" avrebbe probabilmente degli attributi in più, quali ad esempio un oCopertone e relativo cambia_copertone(Copertone c). Se moto ereditasse da "Ruota", si ritroverebbe a propria volta con un attributo oCopertone ed un metodo cambia_copertone() che, una volta applicato alla "Moto" e non alla "Ruota", creerebbe sicuramente qualche problema [:D]

In questo caso invece, le classi "Titolo" e "Abstract" sono estremamente semplici (titolo, getTitolo, setTitolo e nient'altro), e non hanno niente in più che possa essere erroneamente applicato ad "Articolo".

Questo sul piano puramente teorico.

Dal punto di vista pratico invece.... ti faccio ora alcuni brevi esempi del perché avrei preferito usare l'approccio IS-A invece che HAS-A.

Questo è setAbstract di Canale adesso

public function setAbstract($val)
{
$this->oAbstract->setAbstract($val);
$this->changed=true;
}


(nota che comunque questo deve essere copia-incollato in tutte le classi...)

Questo sarebbe setAbstract di Canale se avessi avuto l'ereditarietà multipla


Non c'è niente, perché pensa a tutto la classe da cui eredita (non c'è neanche bisogno di chiamare esplicitamente super()/parent::)

Inoltre, se per qualche strana ragione avessi bisogno di modificare il comportamento di setAbstract, se fosse ereditato potrei semplicemente overloadarlo... mentre con l'approccio corrente avrei sicuramente qualche difficoltà.