2012-07-12 17 views
6

Estoy creando un sistema de salario para empleados. Tengo una clase abstracta Employee. WageEmployee y Manager extienden Employee. Luego, Programmer y SalesPerson extienden WageEmployee.Java, herencia múltiple. ¿Cómo debería hacer esto?

Mi problema es que quiero crear un SalesManager. El SalesManger tiene su pago calculado agregando comisión y un salario. Entonces tienen el tipo SalesPerson y Manager.

¿Qué debería hacer una interfaz y qué debería extenderse SalesPerson?

Es natural ampliar SalesManager desde el administrador, luego hacer SalesPerson una interfaz. Pero no puedo porque hereda de WageEmployee ...

¿Cómo hago para que funcione? ¿correctamente?

abstract class Employee 
{ 
    String name; 

    Employee() {} 
    Employee (String nm) { name = nm; } 
    abstract double computePay(); 
    void display() {} 
    void setHours(double hrs) {} 
    void setSales(double sales) {} 
    void setSalary(double salary) { System.out.println("NO!"); } 

}

+0

¿Hay alguna funcionalidad heredada, o solo son métodos? –

+1

Personalmente, comenzaría con todas las interfaces, esto le dará la mayor flexibilidad posible. Luego, debe averiguar a partir de allí qué implementaciones abstractas producirán la menor cantidad de reelaboración. La única otra solución que tiene es usar una solución de estilo proxy. Es decir, la funcionalidad de una interfaz la implementa un objeto proxy al que el objeto principal mantiene una referencia y llama en su nombre. – MadProgrammer

+1

Las interfaces y la composición del objeto son tus amigos en este caso. –

Respuesta

10

Llámame loco, pero puede que no necesite la subclase para tratar los diferentes métodos de pago aquí. En su lugar, considere usar el Strategy pattern para calcular las comisiones de salarios/ventas. De esta manera, tiene una clase Employee y su subclase SalesEmployee; cada uno de estos tendría como propiedad un objeto PayStrategy, que puede tener subclases concretas WagePayStrategy y CommissionPayStrategy. Si define los métodos correctos en PayStrategy (podría ser una interfaz o clase abstracta), puede hacer que sus instancias Employee pregunten a la estrategia cuáles son los pagos que recibe el empleado por ciertos insumos (horas trabajadas, ventas realizadas, etc.).

Considérese el siguiente ejemplo trivial:

interface PayStrategy { 
    public float getPay(float hoursWorked, float salesMade); 
} 

class WageStrategy implements PayStrategy { 
    public float getPay(float hoursWorked, float salesMade) { 
     return hoursWorked * 8.5; 
    } 
} 

class CommissionStrategy implements PayStrategy { 
    public float getPay(float hoursWorked, float salesMade) { 
     return salesMade * 0.5 + hoursWorked * 5.0; 
    } 
} 

abstract class Employee { 
    public PayStrategy payStrategy; // assign as needed 

    public float getPay(float hoursWorked, float salesMade) { 
     return this.payStrategy.getPay(hoursWorked, salesMade); 
    } 
} 

Nota cómo se puede cambiar la estrategia de pago por cualquier empleado determinado sin necesidad de una clase diferente, dándole más flexibilidad y encapsulación alrededor de ese algoritmo.

+0

Esta es una gran respuesta. –

+0

Por qué, gracias, Luiggi :) – Tim

+0

También es posible que PayStrategy.getPay tome un único valor flotante genérico. Entonces el SalesManager podría tener una implementación de estrategia combinada como la siguiente: float público getPay (flotación ignorada) {return wageStrategy.getPay (getHoursWorked()) + commissionStrategy.getPay (getSalesMade()); } donde la clase SalesManager tiene un campo de ventas y horas trabajadas. – AngerClown

1

Employee tiene métodos getFixedSalary() y getComissionSalary().

Puede crear subclases abstractos SalariedEmployee (getComissionSalary siempre devuelve 0) y hacer Programmer y SalesPerson expandirla. SalesManager implementa directamente Employee.

O todas las clases heredan directamente de Employee, para otorgar la máxima flexibilidad si las escalas de sueldos cambian algún día (yo iría de esta manera). Escriba métodos de ayuda para evitar la duplicación del código, pero le dará opciones para cambiar el modus operandi si fuera necesario.

1

Cuando extienda Clases, generalmente desea conservar algún tipo de funcionalidad y agregarla extendiéndola. Con una interfaz, le da una lista de los métodos que tendrá un objeto.

Parece que tiene Employee s y Manager s, y debe decidir desde qué lugar se extenderá la funcionalidad. Sin mirar su código o modelo de objeto, parece que todos son Employee y algunos de ellos son Manager. Por lo tanto, parece que necesita decidir qué extra hace un Gerente que lo separa de un Empleado. Entonces todo se ampliará a Employee, y ampliará las subclases de Employee (WageEmployee, SalaryEmployee, etc.), luego las que sean Gestores, implementarán una interfaz Manager. Entonces puede tener un SalesPerson extendiendo un WageEmployee y luego un SalesManager extendiendo SalesPerson que implementa Manager.