Not sure if this is the best approach, but I think your approach of using an interface is good (which I'd call IBillable by convention).
But you should not try to accommodate all the required values for the calculation as parameters in the interface method, as this limits your extensibility, what if you come across a new kind of employee who needs one more value for bill calculation. Interface is a contract which should not change, hopefully ever. Method suggested below doesn't have that problem.
One suggestion is to use another class (let's say BillCalculator) and move the different parameters required by the Billable interface to properties of that class.
public abstract class BillCalculator: IBillable
{
abstract decimal Bill();
}
public class HourlyBillCalculator: BillCalculator
{
public int HoursWorked { get; set; }
public decimal PricePerHour { get; set; }
public HourlyBillCalculator(int hoursWorked, decimal pricePerHour)
{
HoursWorked = hoursWorked;
PricePerHour = pricePerHour;
}
public override Bill()
{
// Calculate the Bill
}
}
public class CommisionBillCalculator: BillCalculator {
public decimal CommisionRate { get; set; }
public CommisionBillCalculator(decimal rate)
{
CommisionRate = rate;
}
public override Bill() {
// Calculate the Bill
}
}
Corresponding Calculator class has to be instantiated using a factory pattern or something to fit the need. Then it's just a matter of calling the Bill method, which will use the instance properties to calculate the value.
That will let you keep interface signature consistent.
Note: Syntax may be off, but hope you get the idea.