Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Derived class and override method with derived arguments : how to code it better?

I have a question about Derivation , polymorphism and method signature

I have class

public abstract class PaymentMethod
{   
    public abstract float GetSalary (Employee employee,Vehicule vehicule)
}

and two others

public class MarinePaymentMethod : PayementMethod
{
    public override float GetSalary (Sailor sailor,Boat boat)
}

public class AirPaymentMethod : PayementMethod
{
    public override float GetSalary (Pilot pilot,Plane plane)
}

We assume also that :

public class Sailor : Employee{}
public class Pilot : Employee{}
public class Boat: Vehicule{}
public class Plane: Vehicule{}

So, the "problem" is that this code does not compile , because the signatures are not the same.

I am force to keep the base signature GetSalary(Employee employee, Vehicule vehicule)

and then I must cast in the Derived Payment Method, so that I can use the specific members of Pilot, Sailor, Boat, Plane in these specific payment method.

My first question is: Isn't it a bad smell to cast continuously?

My second question is: How to make a more elegant code Design ? I was thinking about Generics, and create a class like this:

public abstract class PaymentMethod<T, U> where T: Employee where  U: Vehicule 

But then in my code I realize I must put generic almost everywhere I use a payment mehod class and it make the code heavy. Any other solutions ?

Thanks a lot

like image 692
Levis Marc Avatar asked Nov 09 '22 21:11

Levis Marc


1 Answers

Personally, I'd do it this way:

public abstract  class PaymentMethod { 
    public decimal GetSalary(Employee employee, Vehicle vehicle) {
        return GetSalaryImpl(employee, vehicle);
    }    
    protected abstract decimal GetSalaryImpl(Employee employee, Vehicle vehicle);
}
public class MarinePaymentMethod : PaymentMethod {
    public decimal GetSalary(Sailor sailor,Boat boat)
    { throw new NotImplementedException(); /* your code here */ }
    protected override decimal GetSalaryImpl(Employee employee, Vehicle vehicle) {
        return GetSalary((Sailor)employee, (Boat)vehicle);
    }
}    
public class AirPaymentMethod : PaymentMethod {
    public decimal GetSalary(Pilot pilot, Plane plane)
    { throw new NotImplementedException(); /* your code here */ }
    protected override decimal GetSalaryImpl(Employee employee, Vehicle vehicle) {
        return GetSalary((Pilot)employee, (Plane)vehicle);
    }
}
public class Employee {}
public class Vehicle{}
public class Sailor : Employee{}
public class Pilot : Employee{}
public class Boat: Vehicle{}
public class Plane: Vehicle{}

This then works for both polymorphism and overload approaches - although it is unusual that a method that takes an Employee requires a specific type of employee.

like image 169
Marc Gravell Avatar answered Nov 14 '22 22:11

Marc Gravell