Java:Pushing runtime behaviour without Lambda

Java:Pushing runtime behaviour without Lambda



In Java8 one of the best features is Lambda Expression The Idea of Lambda expression is passing a behavior to a method.

This has been adopted from Functional programming, In Functional programming, we can pass a function  as an argument of another function or can returns a function. The function takes a function as an argument or returns a function called
Higher order function.


The benefit of this type of design is you can pass behavior and values together, so a single function can perform all types of actions on those values.

Say, I want to create the calculator so in java we have to create methods like add, subtract, multiply etc. But in the functional program paradigm, we create one method which takes another method as an argument where we define what to do.

Pseudo code
Higher order function

function void caculate (a,b,f){
    f(a,b);
}

Calling

calculate(10,20,funtion(y,z){// define and pass the method on fly

y+z;
});


In Java8 using Lambda, we can do the same if you want to know details about Lambda can consult my post  http://javaonfly.blogspot.in/2016/08/java8-lambda.html


But here we will discuss How we can achieve the same thing without Lambda. As may, many projects has not adopted java 8 due to some restrictions.

We can achieve the same by using  Interface and Anonymous class.

Step 1: Create an Interface which will provide the contract for the behavior/strategy, i.e add, subtract, multiply functionality.

So How we will achieve the same



package com.example.runtime.behaviour;

public interface IStrategy {
   
   public void operation(int operand1,int operand2);

}


Step 2: Next I will create a Calculator class where we create a method called calculate which takes two operands and the IStrategy interface as arguments.

It acts like functional programming Higher order function where we can pass method/behavior runtime.

While calling this calculate method I pass the actual implementation of IStrategy interface by using Anonymous class.

By this way, we can push behavior on runtime without Lambda Expression.


package com.example.runtime.behaviour;

public class Calculator {
   
   public void caculate(int operand1,int operand2,IStrategy runtimeBehaviour){
      runtimeBehaviour.operation(operand1, operand2);
     
   }
   
   public static void testAllOperation(){
     
      Calculator calc = new Calculator();
      calc.caculate(10, 20, new IStrategy(){

          @Override
          public void operation(int operand1, int operand2) {
              int result = operand1+operand2;
              System.out.println("ADD:: " + result);
             
          }
         
      });
     
     
      calc.caculate(10, 20, new IStrategy(){

          @Override
          public void operation(int operand1, int operand2) {
              int result = operand1*operand2;
              System.out.println("Multiply:: " + result);
             
          }
         
      });
   }
   
   public static void main(String[] args) {
      Calculator.testAllOperation();
   }

}



Look at the testAllOperationMethod here we pass two operands 10,20 and implementation of IStrategy one are for add another for multiplication.

So rather creating  4 different methods add, multiply, subtract, the division we can create one method which will support all possible operations taken on operand1 and operand2.

In Future, if any new operation like modulus will be added easily in this approach but if we use one method for one operation then you need to add a new method called modulus to Calculator class which will break Open close principle.

Anonymous Function in java 8 using lambda



Java8 Lambda Expression


In this article, we will discuss Java8 most debated feature Lambda Expression.

What is a Lambda Expression?

In brief, I can say Lambda Expression is the way of passing functions into a function. Where Passing function is being used by the function where it  passed.

Passing function act as a Callback function.

In Java 8 Version Java adopts the Lambda expression actually this is the first step towards functional programming. In functional programming, we can pass a function in another function that is called Higher Order Function.

The benefits of this are Lambda Expression is
As you can pass a function into an another function or I can say you can pass behavior into a function (think function as a behavior). So It is on caller's hand what behavior you can want to do or I can say the strategy is on caller’s hand so it can be altered easily. Prior to this If you want to pass a behavior probably you will create an anonymous class and wrap that behavior in that class and pass it to the another method.

To be specific prior to Lambda expression we will solve this problem that is passing behavior into a method by anonymous class.

Think about Thread and Runnable interface. In Runnable interface there is a run method where we define the behavior or the set activities which should be executed when a thread is spawned.

And we pass this in Thread constructor so when Thread is in running state it performs the activity written in Runnable. But to do we have to create an anonymous class and override public void run then pass it in Thread class.

This not right way to pass a function rather what we did we pass an object where the function is in wrapped form.

Java8 try to get rid of this now no need to create that class directly you can pass a method body to a method.

Let’s take an Example

Suppose I need to compute an Area of Circle and Rectangle and print them so How to do it by lambda Expression.

First I create two functional interfaces, It just a Java interface and it has one method where I specify the behavior template method.

package com.example.java;

public interface Shape {
           
            public int execute(int a,int b);

}


package com.example.java;

public interface Print {
           
            public  void print(int value);

}


Now I create a Class where we define Rectangle and Circle compute behavior and print behavior by Lambda Expression


package com.example.impl;

import com.example.java.Print;
import com.example.java.Shape;

public class ShapeClosure {

           
           
            public void computeArea(Shape shape,Print print,int length,int breadth)
            {
                        int result = shape.execute(length, breadth);                   
                        print.print(result);
            }
           
            public static void main(String[] args) {
                       
                        ShapeClosure closure = new ShapeClosure();
                        Shape circle = (a,b)->(int)3.14f*a*b;                     
                        Print area = (result)->System.out.println("Area of Circle " + result);
                       
                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);
                        closure.computeArea(circle, area, 10, 5);


                       
                       
            }
}

Look at the  ShapeClosure class here I create a ComputeArea Function, the function which will take Shape and Print function as a callback function. In order to do that
Look at the ComputeArea function arguments, it takes shape and Prints functional interface as the argument. Because this functional interface says about the behavior of the function

Shape interface behavior is executed which takes two int argument and return an int
Print interface behavior is print which takes an int argument and prints the value.

In computing are we call this behavior or another way I can say in a function I use callback function's behavior which is the main motto of functional programming


Now look these lines in the main method

Shape circle = (a,b)->(int)3.14f*a*b;                     
                        Print area = (result)->System.out.println("Area of Circle " + result);
                       
                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);
                        closure.computeArea(circle, area, 10, 5);


Here I use Lambda expression as shape’s execute method takes two int’s and compute them so
(a,b)->(int)3.14f*a*b;          

Two arguments int a and b (Don’t need to say data type from functional interface java takes the argument type.)

Now define the body of executing as (int)3.14f*a*b;

So these line is (a,b)->(int)3.14f*a*b;

Is equivalent to

public int execute(int a,int b)
{
  return (int)3.14f*a*b;
}


Same for print , I pass them in computeArea along with data’s which is main intent of functional programming

closure.computeArea(circle, area, 10, 5);


On another way, I can directly pass them in computeArea like this

                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);


when you run the program. You will see Output

Area of Rectangle 200
Area of Circle 150