1 Simulated multiple inheritance Sandro Pedrazzini Approfondimento Simulated multiple inheritance in Java
2 Simulated multiple inheritance Sandro Pedrazzini Multiple inheritance in Java In Java esiste solo eredità semplice (eredità di implementazione) Una classe può però rappresentare più tipi (implementare più interfacce) Ogni relazione di ereditarietà può essere ricondotta a delegation
3 Simulated multiple inheritance Sandro Pedrazzini Classi e tipi PersistentObjFigura Triangolo ElasticObject public interface PersistentObject { void write(); void read(); } public interface ElasticObject { void enlarge(int offset); void restrict(int offset); } public class Triangolo extends Figura implements PersistentObject, ElasticObject {... }
4 Simulated multiple inheritance Sandro Pedrazzini Delegation Utilizzo della composizione al posto dell'ereditarietà ottenendo lo stesso grado di riutilizzo. Dalla relazione "is-a" alla relazione "has-a" Nel caso ideale basterebbe assemblare le varie componenti per realizzare una nuova funzionalità. FilledBox Box FilledBox Box move() box.move() move()
5 Simulated multiple inheritance Sandro Pedrazzini Problema Necessità di estendere contemporaneamente più implementazioni Person (caratteristiche di una persona) Employment (dettagli di una persona impiegata) Employee (caratteristiche complete di un impiegato)
6 Simulated multiple inheritance Sandro Pedrazzini Person public class Person { private String fName; private Date fBirthDate; public Person(String name, Date birthDate) { fName = name; fBirthDate = birthDate; } public String getName(){ return fName; } public Date getBirthDate(){ return fBirthDate; }
7 Simulated multiple inheritance Sandro Pedrazzini Employment public class Employment { private float fSalary; private Date fHireDate; public Employment(float salary, Date hireDate) { fSalary = salary; fHireDate = hireDate; } public float getSalary() { return fSalary; } public Date getHireDate() { return fHireDate; }
8 Simulated multiple inheritance Sandro Pedrazzini Desiderato public class Employee extends Person, Employment {... } Questo non è però possibile in Java Soluzione: - usare delegation per riutilizzare la funzionalità - aggiungere interface per mantenere il polimorfismo => Proxy / Decorator
9 Simulated multiple inheritance Sandro Pedrazzini Extract interfaces (1) public interface IEmployment { float getSalary(); Date getHireDate(); } public class Employment implements IEmployment {... }
10 Simulated multiple inheritance Sandro Pedrazzini Extract interfaces (2) public interface IPerson { String getName(); Date getBirthDate(); } public class Person implements IPerson {... }
11 Simulated multiple inheritance Sandro Pedrazzini Utilizzo delle interface public class Employee implements IPerson, IEmployment {... } In Java una classe può rappresentare più tipi contemporaneamente
12 Simulated multiple inheritance Sandro Pedrazzini Utilizzo delle interface (2) Utilizzando le interface otteniamo riutilizzo di design Come riutilizzare codice? Come sfruttare le implementazioni esistenti di Person e Employment?
13 Simulated multiple inheritance Sandro Pedrazzini Riutilizzo delle classi esistenti public class Employee extends Person implements IPerson, IEmployment {... } oppure: public class Employee extends Employment implements IPerson, IEmployment {... }
14 Simulated multiple inheritance Sandro Pedrazzini Sfruttamento multiplo La soluzione proposta permette di sfruttare attraverso ereditarietà solo una delle implementazioni presenti nelle due classi già disponibili (Person oppure Employment) Per sfruttare la seconda (o eventualmente anche entrambe) potremmo usare la delegation Il polimorfismo è garantito dal fatto di aver implementato le due interfacce
15 Simulated multiple inheritance Sandro Pedrazzini Sfruttamento multiplo (variante 1) IPersonPerson Employee IEmployment Employment
16 Simulated multiple inheritance Sandro Pedrazzini Sfruttamento multiplo (variante 2) IPerson Person Employee IEmployment Employment
17 Simulated multiple inheritance Sandro Pedrazzini Implementazione (variante 1) public class Employee extends Person implements IPerson, IEmployment { private IEmployment fEmploymentMixin; public Employee(String name, Date birthDate, float salary, Date hireDate) { super(name, birthDate); fEmploymentMixin = new Employment(salary, hireDate); } public float getSalary() { return fEmploymentMixin.getSalary(); } public Date getHireDate() { return fEmploymentMixin.getHireDate(); }
18 Simulated multiple inheritance Sandro Pedrazzini Overriding Consideriamo di dover estendere o modificare il comportamento di una classe da cui ereditiamo Person (eredità diretta): semplice overriding Employment (delegation): internal class + semplice overriding
19 Simulated multiple inheritance Sandro Pedrazzini Overriding di Person (1) Consideriamo di voler garantire limmutabilità di Employee Per far questo dobbiamo modificare il metodo getBirthDate() Quello nuovo deve restituirci non il riferimento alloggetto Date, bensì un nuovo oggetto Date (clone)
20 Simulated multiple inheritance Sandro Pedrazzini Overriding di Person (2) public class Employee extends Person implements IPerson, IEmployment { private IEmployment fEmploymentMixin; public Employee(String name, Date birthDate, float salary, Date hireDate) { super(name, birthDate); fEmploymentMixin = new Employment(salary, hireDate); } public float getSalary() { return fEmploymentMixin.getSalary(); } public Date getHireDate() { return fEmploymentMixin.getHireDate(); public Date getBirthDate() { return (Date) super.getBirthDate().clone(); }
21 Simulated multiple inheritance Sandro Pedrazzini Overriding di Employment (1) Sempre considerando di voler garantire limmutabilità di Employee, dobbiamo modificare anche il metodo getHireDate() Quello nuovo deve restituirci non il riferimento alloggetto Date, bensì un nuovo oggetto Date (clone) getHireDate() è un metodo delloggetto delegato
22 Simulated multiple inheritance Sandro Pedrazzini Overriding di Employment (2) Procedimento: –Creiamo una classe interna EmploymentMixin che erediti da Employment e riscriva il metodo getHireDate() –Utilizziamo un riferimento ad un oggetto di EmploymentMixin allinterno della classe Employee
23 Simulated multiple inheritance Sandro Pedrazzini Overriding di Employment (2) Classe interna che estende Employment private static class EmploymentMixin extends Employment { public EmploymentMixin(float salary, Date hireDate) { super(salary, hireDate); public Date getHireDate() { return (Date) super.getHireDate().clone(); }
24 Simulated multiple inheritance Sandro Pedrazzini Overriding di Employment (3) public class Employee extends Person implements IPerson, IEmployment{ private IEmployment fEmploymentMixin; public Employee(String name, Date birthDate, float salary, Date hireDate) { super(name, birthDate); fEmploymentMixin = new EmploymentMixin(salary, hireDate); }... private static class EmploymentMixin extends Employment {... }
25 Simulated multiple inheritance Sandro Pedrazzini Overriding di Employment (4) IPersonPerson Employee IEmployment EmploymentMixin Employment