Methods Over Loading (Polymorphism)and Access Controls in Java

Over Loading Methods and Access Controls

 

One of the OOP’s, strength is polymorphism. Polymorphism can be implemented (achieved) in two ways

1.  1.      Overloading Methods

2.  2.      Overriding Methods will be discussed, in the Inheritance session.(session 4)

  Overloading Methods

When two or more methods in the same class share the same name, with either different parameter signatures or difference in  number of parameters, the methods are said to be over loaded, and the process is referred  to as method overloading.
When java encounters a call to an over loaded method , java uses the type and/ or number of arguments as its guide to determine which version of the overloaded method to actually call.
The method over loading does not depend on return types.

 

  /* consider the example below */

  class OverLoad

 {

           void test()

              {

                System.out.println(“No parameters”);

              }

              void test(int x)

              {

                System.out.println(“x:  “+x);

              }

 

  /*

int test(int x)   // wrong ,as over loading does not depend on return types

{                     //since void test(int x) already exists

    return x;

}

*/

 

 int test(int x,int y)

 {

   return x+y;

 }

 double test(double x)

 {

   return x*x;

 }

 

 }

 

     class OverLoadDemo

    {

             public static void main()

            {

             OverLoad obj = new OverLoad();

             obj.test();

             obj.test(2);

             System.out.println(“int test(int x,int y) method called  ” + obj.test(2,3));

             System.out.println(“double test(int x) method called  ” + obj.test(2.00));

            }

 

     }

 

Explanation:

 When an overloaded method is called, java looks for a match between the arguments used to call the method and method’s parameter. However, this match need not always be exact.In some cases’ java’s automatic type conversion can play a role in method overload resolution, as shown in the below example.

/* */

 

class OverLoad

 {

              void test()

              {

                System.out.println(“No parameters”);

              }

              double test(double x)

              {

                return x;

              }

 }

 class OverLoadDemo1

    {

             public static void main(String args[])

            {

             OverLoad obj = new OverLoad();

             obj.test();

              System.out.println(“when a integer is passed then also test(double x)  method is called  ” +    

             obj.test(2)); //obj.test(2) will invoke test(double x) method

             System.out.println(“when a fraction number is called then also test(double x) method is called  ”  

             +obj.test(2.340)); // obj.test(2.340) will invoke test(double x) method

           }

     }

 Explanation: In the above example method test(int) is not defined,since there is no matching method found, when test() is called with an integer argument, java elevates, to double and then calls test(double), of course if at all test(int) had been defined, it would have been called.

java will employ its automatic type conversions only if no exact match is found.

 Over Loading Constructors

As we overload methods, so is with constructors. We can also over load constructor methods.

lets justify the said, So far we have been passing three parameters to the Box constructor, for every new Box (object) created. What if we wanted to initialize a cube? What if we wanted to create an object which did not care, to what its initial dimensions were? The solution is simple, over load the Box Constructor.

 Consider the previous example

class Box

  {

            double width;

            double height;

            double length;

      Box(double length,double width,double height)

     {

             this.width = width;

             this.height = height;

             this.length = length;

     }

  }

 

   class BoxDemo8

  {

            public static void main(String args[])

            {

              Box MyBox = new Box(23.33,33.33,43.33);

              Box ob = new Box(); //this is illegal, since Box() requires three arguments,its an error to call it  

              //with out them.

              System.out.println(“length of MyBox object is “+ MyBox.length);

              System.out.println(“length of MyBox object is “+MyBox.height);

              System.out.println(“length of MyBox object is “+MyBox.width);

            }          

 }

 

/* The draw back in above program can be over come by over loading constructors */

 class Box

 {

         double width,height,depth;  

           Box()

              {

                 width = -1; // use –1 to indicate an unitialized box

                 height = -1;

                 depth = -1; 

              }

              Box(double side)

              {

                 this.width = side;

                 this.height = side;

                 this.depth = side; 

              }

           Box(double width,double height,double depth)

              {

                 this.width = width;

                 this.height = height;

                 this.depth = depth; 

              }

              double volume()

              {

                return (width*height*depth);

              }

 }

     class OverLoadCons

    {

             public static void main(String args[])

            {

             Box MyBox1 = new Box();

             Box MyBox2 = new Box(23.45);

             Box MyBox3 = new Box(23.33,33.33,43.33);

             System.out.println(“volume of MyBox1  ” + MyBox1.volume());

             System.out.println(“volume of MyBox2  ” + MyBox2.volume());

             System.out.println(“volume of MyBox3  ” + MyBox3.volume());

            }

     }

 

 Passing  Objects as parameters

So far we have seen simple types(int,double) as parameters, However objects’ can be passed, as parameters’ to methods.

The example below illustrates

 

// simple program taking objects as parameters

  class Test

 {

         int i,j;     

               Test()

              {

                i = -1;//-1 indicates that values are

                j = -1;//not constructed at the time of object creation

           

              }

             Test(int x,int y)

              {

                i = x;

                j = y;

              }

           Test(Test obj)

              {

            i  = obj.i;

            j  = obj.j;

              }

          boolean equals(Test obj)

              {         

           if(i == obj.i && j == obj.j)

           return true;

           return false;

              }

  }

     class PassOb

    {

 

        public static void main(String args[])

            {

             Test MyTest1 = new Test(100,22);

             Test MyTest2 = new Test(100,22);

            Test MyTest3 = new Test(MyTest1);

             System.out.println(“MyTest1 = MyTest2 : “+MyTest1.equals(MyTest2) );

             System.out.println();

             System.out.println();

             System.out.println();

             System.out.println(“MyTest3 = MyTest1 : “+MyTest1.equals(MyTest3) );

            }

    }

 

/* Program below takes Box object as parameter */

class Box

 {

           double width,height,depth;

             Box()

              {

                width = -1;

               height = -1;

               depth = -1; 

              }

              Box(double width,double height,double depth)

              {

                this.width = width;

               this.height = height;

               this.depth = depth; 

              }

             Box(Box obj)

              {

              width  = obj.width;

              height = obj.height;

              depth  = obj.depth;

                }

              boolean equals(Box obj)

              {         

               if(width == obj.width && height == obj.height && depth == obj.depth)

               return true;

               return false;

              }

              double volume()

              {

                return (width*height*depth);

              }

 }

 class PassObj

 {

            public static void main(String args[])

            {

             Box MyBox1 = new Box(23.33,33.33,43.33);

             Box MyBox2 = new Box(33.33,43.33,53.33);

            Box MyBox3 = new Box(MyBox1);

            Box MyBox4 = new Box(MyBox2);

            System.out.println(” MyBox1 = MyBox3: “+ MyBox1.equals(MyBox3) +” and volumes are ” + 

                                             MyBox3.volume());

             System.out.println();

             System.out.println();

             System.out.println(“MyBox2 = MyBox4 : ” + MyBox2.equals(MyBox4) +” volume= “+

                                            MyBox4.volume());

            }

    }

A Closer Look At Argument Passing

There are two ways of passing arguments to a subroutine(function).

1.Call By Value

2.Call By Reference

1. Call By Value:  In this approach  the value of an argument, is copied  into the formal parameter of the subroutine (function)., there by any changes made to the parameter of the subroutine, has no effect on the value of the argument

2.Call By reference : In this approach  the reference of an argument(not value of the argument), is passed  to the formal parameter of the subroutine (function)., there by any changes made to the parameter of the subroutine, Inside the subroutine, this reference is used to access the actual argument specified in the call. This means that changes, made to the parameter of the subroutine, will affect, the value of the argument used to call the subroutine.

 

Java uses both approaches, depending up on what is passed, whether it’s a simple type or object.

 

If a   simple type, then Call By Value approach is used.
If an object type, then Call By Reference approach is used.

 

Let’s examine each approach with the help of examples

 // Simple Types are passed by value

 class Test

{

  void meth(int i, int j)

  {

    i *= 2;

    j /= 2;

  }

}

 class CallByValue

{

  public static void main(String args[])

  {

    Test MyTest = new Test();

    int x =15,y = 20;

    System.out.println();

    System.out.println();

    System.out.println(“values of x and y before call to meth() function made”);

    System.out.println(“x = “+x+”y = “+y);

     System.out.println();

     System.out.println(“values of x and y after call to meth() function made”);

     System.out.println(“x = “+x+”y = “+y);

 }

}

 

Explanation: as You can see the operations occurred in meth() funtion have, no effect on the value of x and y,used in the call,Thus their values did not change to 30 and 10.

But when ever we pass an object to a method, the situation changes dramatically, objects are passed by reference. changes made to the object in the subroutine (function), do affect the object used as an argument.

when creating a variable of class type,we are actually creating a reference to an object.So when objects are passed as arguments to a method, the parameter that receives, will actually receive the reference of the same object ,which is referenced by the argumenth,Hence objects  are passed by use of reference.

 // Objects are passed by reference

class Test

{

  int i,j;

  Test(int i,int j)

  {

    this.i = i;

    this.j = j;

  }

   void meth(Test obj)

  {

   obj.i*=2;

   obj.j/=2;

  } 

 }

 class CallByRef

{

  public static void main(String args[])

  {

    Test MyTest1 = new Test(15,20);

System.out.println(“values of i  and j, in MYTest1,before call to meth() function made”);

System.out.println(“i = “+MyTest1.i+”j = “+MyTest1.j);

MyTest1.meth(MyTest1);

System.out.println();

System.out.println();

System.out.println(“values of i and j in MyTest1,after call to meth() function made”);

System.out.println(“i = “+MyTest1.i+”j = “+MyTest1.i);

  }

}

Remember: Simple types are passed to subroutine by CallByValue and Objects are passed by use of Call By Reference.

Returning Objects

So far we had methods returning primary type data but a method is also capable of returning class types,that we create(ie objects).

the example below, best illustrates

 //returning class types ie returning objects

 class Test

{

  int i,j;

  Test(int i,int j)

  {

    this.i = i;

    this.j = j;

}

   Test meth(Test obj)

  {

   obj.i*=2;

   obj.j/=2;

   return obj;

  } 

 }

 class RetObj

{

  public static void main(String args[])

  {

    Test MyTest1 = new Test(15,20);

    Test MyTest2;

    System.out.println(“values of i  and j, in MYTest1,before call to meth() function made”);

   System.out.println(“i = “+MyTest1.i+”j = “+MyTest1.j);

   MyTest2 = MyTest1.meth(MyTest1);

   System.out.println();

   System.out.println();

   System.out.println(“values of i and j in MyTest2,after call to meth() function made”);

   System.out.println(“i = “+MyTest2.i+”j = “+MyTest2.i);

  }

}

 // consider this example

class Test

{

  int a;

  Test(int i)

  {

    a = i;

   }

 

  Test IncrByTen()

  {

   Test temp = new Test(a+10);  

   return temp;

  } 

 }

 class RetObj1

{

  public static void main(String args[])

  {

    Test ob1 = new Test(2);

    Test ob2;

    ob2 = ob1.IncrByTen();

    System.out.println(“value in variable a before call to Test IncrByTen() method”);

    System.out.println(“value of a = “+ob1.a);

    System.out.println(“value in variable a after call to Test IncrByTen() method”);

    System.out.println(“”+ob2.a);

  }

}

 Explanation : The preceding program makes another important point, since all objects are dynamically allocated using “new”, You need not worry about an object going out of scope because the method in which it was created terminates .The object will continue to exist as long as there is reference to it some where in the program.

 Recursion : is the process of defining something it terms of itself.

 Java supports recursion.

In java programming, recursion is the attribute that allows a method to call it self.

A method that call’s itself is said to be recursive.

 // A simple example of recursion

 class Factorial

{

  int fact(int n)

      {

        int result=1;

           if (n == 1)

          return 1;

        else

        {

          result = fact(n-1) * n;

          return result;

        } 

       }       

}

 class RecursionDemo

{

  public static void main(String args[])

  {

    Factorial f = new Factorial();

    System.out.println();

    System.out.println(“factorial of 4 is : “+f.fact(4));

    System.out.println();

    System.out.println(“factorial of 10 is : “+f.fact(10));

    System.out.println();

    System.out.println(“factorial of 9 is : “+f.fact(9));

    System.out.println();

    System.out.println(“factorial of 8 is : “+f.fact(8));

  }

}

 Explanation : here how it works : when fact() is called with an argument of 4, the first call to fact() will cause a second call to be made with the argument of 3.This second call will cause fact(), be called third

time with an argument of 2.This Third call will cause fact(), be called fourth time with an argument 1.This will return 1.

Now 1 (The value of n in 4th  call to fact() )is multiplied with 2 (The value of n in 3rd call) and again the product, is multiplied with 3(The value of n in 2nd call to fact() )  and the product is again multiplied by 4 (The value of n in 1st  call of fact()).

 Remember : While writing recursive methods, you must have an if satement some where to force method to return with out recursive call, being executed. If if statement is not used then, once you call the method, it  will never return. This is a very common error in working with recursion.

 // Another example that uses recursion.

 class RecTest

{

  int values[];

       RecTest(int i)

      {

         values = new int[i];

      }       

//display array recursively

       void PrintArray(int i)

      {

         if (i == 0)

               return;//return o;

         else

               PrintArray(i-1);

System.out.println(“[“+(i-1)+”]   “+values[i-1]);

             

      }

}

 class RecursionDemo1

{

  public static void main(String args[])

  {

    RecTest ob = new RecTest(10);

     for(int i=0;i<10;i++ )

    ob.values[i]=i;

     ob.PrintArray(10);

  }

}

Introducing Access Control

Access Control: Encapsulation links data with code that manipulates it, However, Encapsulation also provides another important attribute access control.

Using access control, we can prevent misuse of the data, Thus when correctly implemented, a class creates a “black box” which may be used, but the inner workings are not open to tampering.

So access control can be implemented with the help of the following, set of access specifiers’,

So how a member can be accessed is determined by one, these access specifiers’ which are specified while declaration of the,members.

1)protected Applies only when inheritance is used, suppose in a package a method of a class is declared as protected then within the same package it can be accessed but if the same method is to be accessed with in another package then the class containing that method should be first inherited and then the inheriting class object can access the protected method.

2)public When a member of a class is modified by the public specifier, then that member can be accessed from any where with in the entire environment. for example main() method (which has public as access specifier).

 3)private When a member of a class is specified as private, then that member can be accessed, only other members of its class.(that’s why main() is specified as public, so that it can be called from any where, by the java runtime system environment).

 4)default When no access specifier is used, then by default the member of  a class is public, with in its own package.

 so far in the programs, all the members of a class have used default access mode. which are public, with in its own package.

 syntax:

AccessSpecifier  type [ VariableName or MethodName ] ;

 for example

 private int x; public double y;

 private int MyMethod(ParameterList)

{

  // statements;

}

 /*

 This program demonstrates the difference between public and private

*/

 class Test

{

     int a; // default access

     public  int b;//public access

     private int c;//private access

 //   methods to access

     void Setc(int i)

    {

      c = i;

    }

    int getc()

    {

     return c;

    }

}

 class AccessTest

{

  public static void main(String args[])

  {

    Test ob = new Test();

    ob.a = 10; //This is ok,’a’ variable can be accessed directly by object.

    ob.b = 20; //This is ok,’b’ variable can be accessed directly by object.

    ob.c = 100; /* Error,as ‘c’ variable can not be accessed directly by object,because    

                    access is private,so it has to be accessed through methods of a class   

                   as shown below */

    ob.Setc(100) ;//This is ok

    System.out.println(“value of a = “+ob.a); /* This is ok, variable can be accessed       

                                                 directly by object. */

    System.out.println(“value of b = “+ob.b);/* This is ok variable can be accessed directly

                                                by object.*/

     System.out.println(“value of c = “+ob.c);/*  Error,as ‘c’ variable can not be accessed 

                                                  directly by object but can be accessed as 

                                                  shown below with method getc()  */

 

    System.out.println(“value of c = “+ob.getc());                                         

   }

}

 To see how the access control can be applied to more practical example, consider the previous stack program.

 // program TestStack.java revisited and observe the changes made with prevoius

  /*       A simple program demonstrating the ability to use classes     */

   class stack

  {

   private  int stack[] = new int[10];

   private int tos;

     stack()

     {

     tos = -1;

     }

       void push(int item)

     {

     stack[++tos] = item;

     }

      int pop()

     {

      return (stack[tos–]);

     }

      int pop(int count)

     {

      return (stack[count]);

     }

  }

   class TestStack

  {

            public static void main(String args[])

            {

          stack MyStack = new stack();

          //Fill the stack with items using for loop

          for(int i = 1; i<=10 ; i++)

          MyStack.push(i);

           System.out.println(“items as entered in the stack last in last out”);

          for (int i = 0 ;i<10 ;i++)

          System.out.println(“value in stack ” + MyStack.pop());

           MyStack.stack[5] = 100; /*   Error ,as  Tampering of the data is not possible,as object   

                                                         cannot access stack[5] directly, specified is private */

           System.out.println(” item  in stack[5] is = ” + MyStack[5]); /*  Error ,as  Tampering of the data is

                                                                                                          not possible,as object cannot access 

                                                                                                          stack[5] directly ,since access 

                                                                                                           specified is private  */

             }          

  }

 Remember: In real world instance variables’ (member variables of a class), are allowed to be accessed only through code (member functions of class), that is, method.

 

 

The author is a trainer and developer in oracle and java technogies. you can reach him on [email protected]

Subscribe to Our Feed!

Enter your email address:

Delivered by FeedBurner