anonymous inner class as an approach of passing functions to other functions

In the previous post we discussed about what is anonymous inner class. Now we can look into how the anonymous inner class can be used for passing functionalities to other methods. Usually in java, we pass values to methods, or in other words method parameters are usually values or objects holding the values.

First class functions

In programming there is a concept called First class functions, which means in some programming language we can pass functions as an argument to another functions. Callbacks in javascript is a typical example for this. In java, we cannot pass functions to another functions. But we can achieve the same with anonymous inner classes. An interface with single method is sometimes called as functional interface. An anonymous inner class implementing a functional interface can be passed to another function as an argument and we can achieve the feature ‘passing functionalities across’.

Passing values, the usual way

As always, lets start with a scenario we want to address. A company, having a number of employees decided to give bonus to its employees. Each month they will celebrate as a ‘Role month’ and give bonus to employees of that ‘Role’. For example January is ‘developer month’ and all developers will get bonus along with salary in January. February is testers month and all testers will get bonus, and so on.

Lets write code for calculating salary of each employee, for each month. So lets create a class named Employee.

As you can see the salary is same as basicPay initially. We will add bonus to salary later based on month and employee role.

Now we can create a class named EmployeeAdmin which is having a number of employees.

Note: if you are not familiar with the way ArrayList is created with double curly brackets {{ ..... }}, this is an alternate approach to the usual way

and this feature is available from java6.

Next task is to iterate over the employees and calculate the salaries for each month. For calculating the salary we will create a class, say SalaryAdmin which has different functions to calculate salary based on month. As January is ‘developer’ month, we will calculate salary for January first.

Now we can check whether this works as expected. So go back to the EmployeeAdmin class and iterate over employees to calculate salaries. The EmployeeAdmin.java becomes as follows now.

And see the output below, all developers got a bonus while others got their basic pay.

Lets calculate salary for February. So the corresponding method is added to class SalaryAdmin and SalaryAdmin.java now becomes as follows.

And on running the EmployeeAdmin.java with the following code,

will give the following output.

So, basically in ‘Manager month’ (say in march), there will be an another function probably with the name setSalaryForMarch in the class SalaryAdmin. As in each month, the ‘rule’ for calculating the salary varies, in the upcoming months there will be additional functions added to the class.

If you have a different rule like ‘bonus is available for employess who has salary less than 20000’ then there will be another function for that rule. So we can say as the number of rule increases, there will be additional functions. This increase in the ‘number of functions’ is because we ‘passed the values’ to functions which calculates on those values, ie. we passed the values in Employee to the functions named setSalaryForJanuary, setSalaryForFebruary which calculated on Employee.

You may be able to achieve the same functionality with a single function which has if...else or switch...case but that would result in much more messy and more ‘difficult to read’ code than the above approach especially with increased number of ‘rules’.

Passing functionalities, the java way

In this approach, we will pass the ‘functionalities’ to calculate the bonus. The functionality in our case is the ‘rule’ which ‘enables the employee’ to gain the bonus. So in this approach we will give bonus to employees who is eligibleForBonus and later we pass ‘rules’ which makes them eligibleForBonus.

Lets create an interface BonusPayable with which we can take an Employee and decide whether he is eligibleForBonus. But remember, the ‘rule’ to decide whether he is eligibleForBonus will be defined later based on the month. So the interface is defined below.

Now, instead of creating each function for adding the bonus for each month (which we did in SalaryAdmin before), here we will create a single function which will add the bonus if the employee is eligibleForBonus. The function is given below.

As you can see the above function is a generic one, which we can use for all the months or all the rules. This function just says ‘the bonus will be given if the employee is eligible for bonus’. And the ‘eligibility’ (ie. ruleOfMonth) is passed to this method. As we will pass the ‘rule’ to this method, this is the way of passing functionalities to method.

To check everything we can use the class EmployeeAdmin which we created already, and change it to include our new functions, as follows.

Now, it is just a question of ‘how to define the rules for each month’. Well, all we need to do is just define an anonymous inner class which will satisfy the condition for January, ie. ‘all developers will get bonus’, then passing that anonymous inner class to the method calculateEmployeeSalaries.

Putting everything to EmployeeAdmin, the class becomes as shown below.

which will give the following result.

we can see that all developers got bonus. Now for February all testers will get bonus, so all you have to do is change the rule, like follows.

You can see all testers got bonus from the below result.

If you want to add multiple conditions in the rule like only managers having a basicPay less than 20000 will get bonus, you can change the rule accordingly. See the code below.

So in this way, using anonymous inner classes we can pass functionalities to other functions in java. And…..thats it.

Happy coding….

Leave a Comment

Your email address will not be published. Required fields are marked *