public interface IPayable { decimal GetPaymentAmount(); // calculate payment; no implementation } // end interface IPayable _________________________________________ public abstract class Employee { // read-only property that gets employee's first name public string FirstName { get; private set; } // read-only property that gets employee's last name public string LastName { get; private set; } // read-only property that gets employee's social security number public string SocialSecurityNumber { get; private set; } // three-parameter constructor public Employee( string first, string last, string ssn ) { FirstName = first; LastName = last; SocialSecurityNumber = ssn; } // end three-parameter Employee constructor // return string representation of Employee object, using properties public override string ToString() { return string.Format( "{0} {1}\nsocial security number: {2}", FirstName, LastName, SocialSecurityNumber ); } // end method ToString } // end abstract class Employee __________________________________________________________ public class HourlyEmployee : Employee { private decimal wage; // wage per hour private decimal hours; // hours worked for the week // five-parameter constructor public HourlyEmployee( string first, string last, string ssn, decimal hourlyWage, decimal hoursWorked ) : base( first, last, ssn ) { Wage = hourlyWage; // validate hourly wage via property Hours = hoursWorked; // validate hours worked via property } // end five-parameter HourlyEmployee constructor // property that gets and sets hourly employee's wage public decimal Wage { get { return wage; } // end get set { if ( value >= 0 ) // validation wage = value; else throw new ArgumentOutOfRangeException( "Wage", value, "Wage must be >= 0" ); } // end set } // end property Wage // property that gets and sets hourly employee's hours public decimal Hours { get { return hours; } // end get set { if ( value >= 0 && value <= 168 ) // validation hours = value; else throw new ArgumentOutOfRangeException( "Hours", value, "Hours must be >= 0 and <= 168" ); } // end set } // end property Hours // calculate earnings; override Employee’s abstract method Earnings public override decimal Earnings() { if ( Hours <= 40 ) // no overtime return Wage * Hours; else return ( 40 * Wage ) + ( ( Hours - 40 ) * Wage * 1.5M ); } // end method Earnings // return string representation of HourlyEmployee object public override string ToString() { return string.Format( "hourly employee: {0}\n{1}: {2:C}; {3}: {4:F2}", base.ToString(), "hourly wage", Wage, "hours worked", Hours ); } // end method ToString } // end class HourlyEmployee _____________________________________________ public class CommissionEmployee : Employee { private decimal grossSales; // gross weekly sales private decimal commissionRate; // commission percentage // five-parameter constructor public CommissionEmployee( string first, string last, string ssn, decimal sales, decimal rate ) : base( first, last, ssn ) { GrossSales = sales; // validate gross sales via property CommissionRate = rate; // validate commission rate via property } // end five-parameter CommissionEmployee constructor // property that gets and sets commission employee's gross sales public decimal GrossSales { get { return grossSales; } // end get set { if ( value >= 0 ) grossSales = value; else throw new ArgumentOutOfRangeException( "GrossSales", value, "GrossSales must be >= 0" ); } // end set } // end property GrossSales // property that gets and sets commission employee's commission rate public decimal CommissionRate { get { return commissionRate; } // end get set { if ( value > 0 && value < 1 ) commissionRate = value; else throw new ArgumentOutOfRangeException( "CommissionRate", value, "CommissionRate must be > 0 and < 1" ); } // end set } // end property CommissionRate // calculate earnings; override abstract method Earnings in Employee public override decimal Earnings() { return CommissionRate * GrossSales; } // end method Earnings // return string representation of CommissionEmployee object public override string ToString() { return string.Format( "{0}: {1}\n{2}: {3:C}\n{4}: {5:F2}", "commission employee", base.ToString(), "gross sales", GrossSales, "commission rate", CommissionRate ); } // end method ToString ___________________________________ public class BasePlusCommissionEmployee { private decimal baseSalary; // base salary per week // six-parameter constructor public BasePlusCommissionEmployee( string first, string last, string ssn, decimal sales, decimal rate, decimal salary ) { BaseSalary = salary; // validate base salary via property } // end six-parameter BasePlusCommissionEmployee constructor // property that gets and sets // base-salaried commission employee's base salary public decimal BaseSalary { get { return baseSalary; } // end get set { if ( value >= 0 ) baseSalary = value; else throw new ArgumentOutOfRangeException( "BaseSalary", value, "BaseSalary must be >= 0" ); } // end set } // end property BaseSalary // calculate earnings; override method Earnings in CommissionEmployee public override decimal Earnings() { return BaseSalary + base.Earnings(); } // end method Earnings // return string representation of BasePlusCommissionEmployee object public override string ToString() { return string.Format( "base-salaried {0}; base salary: {1:C}", base.ToString(), BaseSalary ); } // end method ToString } // end class BasePlusCommissionEmployee ______________________________________________ public class SalariedEmployee : Employee { private decimal weeklySalary; // four-parameter constructor public SalariedEmployee( string first, string last, string ssn, decimal salary ) : base( first, last, ssn ) { WeeklySalary = salary; // validate salary via property } // end four-parameter SalariedEmployee constructor // property that gets and sets salaried employee's salary public decimal WeeklySalary { get { return weeklySalary; } // end get set { if ( value >= 0 ) // validation weeklySalary = value; else throw new ArgumentOutOfRangeException( "WeeklySalary", value, "WeeklySalary must be >= 0" ); } // end set } // end property WeeklySalary // calculate earnings; override abstract method Earnings in Employee public override decimal Earnings() { return WeeklySalary; } // end method Earnings // return string representation of SalariedEmployee object public override string ToString() { return string.Format( "salaried employee: {0}\n{1}: {2:C}", base.ToString(), "weekly salary", WeeklySalary ); } // end method ToString } // end class SalariedEmployee ______________________________________________ public class PayrollSystemTest { public static void Main( string[] args ) { // create derived class objects SalariedEmployee salariedEmployee = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00M ); HourlyEmployee hourlyEmployee = new HourlyEmployee( "Karen", "Price", "222-22-2222", 16.75M, 40.0M ); CommissionEmployee commissionEmployee = new CommissionEmployee( "Sue", "Jones", "333-33-3333", 10000.00M, .06M ); BasePlusCommissionEmployee basePlusCommissionEmployee = new BasePlusCommissionEmployee( "Bob", "Lewis", "444-44-4444", 5000.00M, .04M, 300.00M ); Console.WriteLine( "Employees processed individually:\n" ); Console.WriteLine( "{0}\nearned: {1:C}\n", salariedEmployee, salariedEmployee.Earnings() ); Console.WriteLine( "{0}\nearned: {1:C}\n", hourlyEmployee, hourlyEmployee.Earnings() ); Console.WriteLine( "{0}\nearned: {1:C}\n", commissionEmployee, commissionEmployee.Earnings() ); Console.WriteLine( "{0}\nearned: {1:C}\n", basePlusCommissionEmployee, basePlusCommissionEmployee.Earnings() ); // create four-element Employee array Employee[] employees = new Employee[ 4 ]; // initialize array with Employees of derived types employees[ 0 ] = salariedEmployee; employees[ 1 ] = hourlyEmployee; employees[ 2 ] = commissionEmployee; employees[ 3 ] = basePlusCommissionEmployee; Console.WriteLine( "Employees processed polymorphically:\n" ); // generically process each element in array employees foreach ( Employee currentEmployee in employees ) { Console.WriteLine( currentEmployee ); // invokes ToString // determine whether element is a BasePlusCommissionEmployee if ( currentEmployee is BasePlusCommissionEmployee ) { // downcast Employee reference to // BasePlusCommissionEmployee reference BasePlusCommissionEmployee employee = ( BasePlusCommissionEmployee ) currentEmployee; employee.BaseSalary *= 1.10M; Console.WriteLine( "new base salary with 10% increase is: {0:C}", employee.BaseSalary ); } // end if Console.WriteLine( "earned {0:C}\n", currentEmployee.Earnings() ); } // end foreach // get type name of each object in employees array for ( int j = 0; j < employees.Length; j++ ) Console.WriteLine( "Employee {0} is a {1}", j, employees[ j ].GetType() ); } // end Main } // end class PayrollSystemTest