Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / September 2006

Tip: Looking for answers? Try searching our database.

Can a method be a parameter of another method in Java?

Thread view: 
Shawn - 13 Sep 2006 13:46 GMT
Hi,

In a precedual language world, a method can take a parameter which is a
 method by itself. For example,

<psudo-code>

sum_from_a_to_b(myFunc, a, b);   //a is 1, b is 5

by passing different myFunc,

sum_from_a_to_b=1+2+3+4+5;
or
sum_from_a_to_b=1^2+2^2+3^2+4^2+5^2;
or
sum_from_a_to_b=1^3+2^3+3^3+4^3+4^3;
or
sum_from_a_to_b=(1+50)^2+(2+50)^2+...+(5+50)^2;
or
anything you specified in myFunc.

This strategy is very powerful because it elevated one level higher by
abstraction. Can Java do something similar? If not, how Java get around it?

Thank you very much. I greatly appreciate any feedback.
Ingo R. Homann - 13 Sep 2006 13:51 GMT
Hi,

> Hi,
>
[quoted text clipped - 19 lines]
> This strategy is very powerful because it elevated one level higher by
> abstraction. Can Java do something similar?

Of course it can, see below. A great advantage of Java is, that its
solution is also typesafe!

Ciao,
Ingo

interface Mapper {
  int map(int d);
}

class Test {

 double sum(Mapper m, int a, int b) {
  int sum=0;
  for(int i=a;i<=b;i++) {
   sum+=m.map(i);
  }
  return sum;
 }

 void test() {
  System.out.println(sum(
   new Mapper(){public int map(int x) {return x*x;}},
   5,10));
  System.out.println(sum(
   new Mapper(){public int map(int x) {return (x+50)*(x+50);}},
   5,10));
  // ...
 }

}
Shawn - 13 Sep 2006 14:10 GMT
> Of course it can, see below. A great advantage of Java is, that its
> solution is also typesafe!
[quoted text clipped - 27 lines]
>
> }

Fantastic! Thank you very much. I didn't realize interface can be such a
use--place holder. I thought interface was only used in inheritance.

One more question about the "public" word:

interface Mapper {
   int map(int d);  //Did you forget "public" here?
}
..
System.out.println(sum(
    new Mapper(){public int map(int x) {return x*x;}},
    5,10));   //I assume you add public here so Mapper m can access
.map(). If you omit it above, can you enforce it now?

Thank you again.
Michael Rauscher - 13 Sep 2006 14:35 GMT
Shawn schrieb:

>> Of course it can, see below. A great advantage of Java is, that its
>> solution is also typesafe!
[quoted text clipped - 36 lines]
>    int map(int d);  //Did you forget "public" here?
> }

No, Ingo didn't forget the public. A interface only have public methods
so the public keyword may be omitted.

Bye
Michael
Ingo R. Homann - 13 Sep 2006 15:52 GMT
Hi,

> Fantastic! Thank you very much. I didn't realize interface can be such a
> use--place holder. I thought interface was only used in inheritance.

I do not see any difference!

A class can implement an interface and therefore must implement the
method defined in this interface. So, the class is a subtype of the
interface (->inheritance). Now, if you want to access the method, you
only need a reference to some Object which has the type/subtype of the
interface, therefore, the interface is a place holder (if you want to
call it so)...

Ciao,
Ingo
Bent C Dalager - 13 Sep 2006 16:56 GMT
>Hi,
>
[quoted text clipped - 6 lines]
>method defined in this interface. So, the class is a subtype of the
>interface (->inheritance).

I think we should maintain a distinction between inheritance and
implementation: the class does not inherit from the interface, but
rather it implements the interface. A class can only inherit from
other classes, not from interfaces.

I would therefore say that Shawn is right in concluding that
interfaces aren't just used for inheritance. (And to the extent that
interfaces are involved in inheritance at all, it's only when they
inherit from other interfaces - but interface inheritance is somewhat
an different beast than class inheritance.)

Cheers
    Bent D
Signature

Bent Dalager - bcd@pvv.org - http://www.pvv.org/~bcd
                                   powered by emacs

AndrewMcDonagh - 13 Sep 2006 20:15 GMT
>> Hi,
>>
[quoted text clipped - 19 lines]
> Cheers
>     Bent D

Actually they are called Interface Inheritance and Implementation
Inheritance

Java keywords is 'implements' but that is not the OO term.

This is why Java supports Multiple Interface Inheritance, but not
Multiple Implementation Inheritance.

Andrew
Mark Space - 13 Sep 2006 19:42 GMT
>> Of course it can, see below. A great advantage of Java is, that its
>> solution is also typesafe!
[quoted text clipped - 11 lines]
>>   ...
>>  }

> Fantastic! Thank you very much. I didn't realize interface can be such a
> use--place holder. I thought interface was only used in inheritance.

Don't overlook the use of Interface in conjunction with other forms of
inheritance at the same time:

class hickey extends dohickey implements blah, Mapper {
...
}

Now a class that does a lot of things (like things you need for your
design) can also be used for a Mapper object.  This particular pattern
happens a lot in Swing, for example, especially for action listeners, so
be on the look out for it.

Also, there is another way of doing what you ask.  The Method object
corresponds much more closely to a C function pointer:

class myInvoker( Method func_ptr )
{
    funct_ptr.invoke();
}

static main (args[])
{
    Object o = new Integer();
    Class[] parameterTypes = new Class[] {String.class};
    Method m = = c.getMethod("concat", parameterTypes);

    myInvoker( m );
}

Except that there's a lot more needed than that (I omitted big try ...
catch blocks, for starters).  However, the Method object can be used to
sling methods around something like C functions.

What this is useful for is when you can't use Interfaces.  For example,
you are passed an Object, and you'd like to be able to access methods by
name.  A method called "getName" which returns a string, and a method
called "setName(String)" could be used to set a property called Name in
the Object, and there's no need for any Interface or inheritance at all.
 This provides a lot of flexibility for your programs.

You can also look at an Object, and find what Interfaces it implements,
and even pick and choose which Interfaces you want.  For example, you
might want Mapper2_0, but you'll settle for Mapper1_0.  Again, lots of
flexibility for your programs.

The whole subject is called Reflection, for more go to:

Finding Interface:
http://java.sun.com/docs/books/tutorial/reflect/class/getInterfaces.html

Invoking methods, the real example:
http://java.sun.com/docs/books/tutorial/reflect/object/invoke.html

More reflection, the whole she-bang:
http://java.sun.com/docs/books/tutorial/reflect/index.html
Shawn - 13 Sep 2006 18:50 GMT
Hi,

Could you provide me one more example to achieve the following effect in
Java? Thank you very much.

var a = [1,2,3];
   
    for (i=0; i<a.length; i++)
    {
        a[i] = a[i] * 2;
    }
   
    for (i=0; i<a.length; i++)
    {
        alert(a[i]);
    }
Doing something to every element of an array is pretty common, and you
can write a function that does it for you:

    function map(fn, a)
    {
        for (i = 0; i < a.length; i++)
        {
            a[i] = fn(a[i]);
        }
    }
Now you can rewrite the code above as:

    map( function(x){return x*2;}, a );
    map( alert, a );
Shawn - 13 Sep 2006 19:43 GMT
> Hi,
>
[quoted text clipped - 26 lines]
>     map( function(x){return x*2;}, a );
>     map( alert, a );

Sorry. I try to do it myself. If anything wrong, please point it out for
me. Thank  you.

interface Mapper {
  void map(int[] d);
}

class Test {

 void doSomethingToArray(Mapper m, int[] aArray) {
    m.map(aArray);
  } //end of method doSomethingToArray

Mapper squareArray = new Mapper()
{
    void map(int[] a)
    {
        for (int i=0; i<a.length; i++)
        {
            a[i] *= a[i];
        }
    }
}

Mapper printArray = new Mapper()
{
    void map(int[] a)
    {
        for (int i=0; i<a.length; i++)
        {
            System.out.println(a[i]);
        }
    }
}

 void test() {
    int[] a={2, 4, 6, 8};
    doSomethingToArray(squareArray, a);
    doSomethingToArray(printArray, a);
 }

} //end of class Test
Shawn - 13 Sep 2006 20:02 GMT
> Hi,
>
[quoted text clipped - 26 lines]
>     map( function(x){return x*2;}, a );
>     map( alert, a );

I tried the following file Test.java. It didn't work.

/*
For testing passing a method as a method parameter
*/

interface Mapper {
  void map(int[] d);
}

class Test {

        void doSomethingToArray(Mapper m, int[] aArray) {
                m.map(aArray);
        } //end of method doSomethingToArray

        Mapper squareArray = new Mapper() {
                void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                a[i] *= a[i];
                        }
                }
        }

        Mapper printArray = new Mapper() {
                void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                System.out.println(a[i]);
                        }
                }
        }

        static int[] a={2, 4, 6, 8};

        public static void main(String[] args)
        {
                doSomethingToArray(squareArray, a);
                doSomethingToArray(printArray, a);
        }

} //end of class Test

Below is the error message. I cannot solve it. Back to the interface
issue, I am not allowed to instantiate an interface even I implement its
method?

Thank you very much for your help.

>javac Test.java
----------
1. ERROR in Test.java (at line 25)
        Mapper printArray = new Mapper() {
        ^^^^^^
Syntax error on token "Mapper", ";", "," expected
----------
2. ERROR in Test.java (at line 39)
        doSomethingToArray(squareArray, a);
                           ^^^^^^^^^^^
Cannot make a static reference to the non-static field squareArray
----------
3. ERROR in Test.java (at line 40)
        doSomethingToArray(printArray, a);
                           ^^^^^^^^^^
Cannot make a static reference to the non-static field printArray
----------
3 problems (3 errors)
AndrewMcDonagh - 13 Sep 2006 20:17 GMT
>> Hi,
>>
[quoted text clipped - 59 lines]
>                         }
>                 }
         }  ;

you are missing a ';' on the '}' above

>         static int[] a={2, 4, 6, 8};
>
[quoted text clipped - 30 lines]
> ----------
> 3 problems (3 errors)
Ingo R. Homann - 14 Sep 2006 08:16 GMT
Hi,

> /*
> For testing passing a method as a method parameter
[quoted text clipped - 29 lines]
>                 }
>         }

Besides the missing ';', there is another design-flaw IMHO. I would do
it like this:

interface Mapper {
  int map(int a);
}

class Test {
  void doSomethingToArray(int[] as, Mapper m) {
    for(int i=0;i<as.length;i++) {
      as[i]=m.map(as[i]);
    }
  }
}

Mapper square=new Mapper() {
  int map(int i) {
    return i*i;
  }
}

Mapper print=new Mapper() {
  int map(int i) {
    System.out.println(i);
    return i; // (*)
  }
}

(*) here you can see, that "printing" is not really a kind of
"Mapper"-function.

Ciao,
Ingo
Shawn - 14 Sep 2006 13:57 GMT
> Besides the missing ';', there is another design-flaw IMHO. I would do
> it like this:
[quoted text clipped - 29 lines]
> Ciao,
> Ingo

Thank you. Could you kindly provide "public static void main() " to show
me how to use it. As you see, I am a little lost here: in the same Java
file or in the different file? If in the same file, what the file name
should be?(Test.java or interface.java?) Do I have to make
doSomethingToArray static?

I still like my previous not-running program, because in yours, as you
said, Mapper print is "silly" and in the for loop inside
doSomethingToArray, as[i] = m.map(as[i]) is not needed in my program. My
code is more intuitive. The reason I want to pass a method as a
parameter into another method is to have more abstraction(clear mind
clutter). Your implementation brings other extra into the code. My goal
is half-achieved, though.
Ingo R. Homann - 15 Sep 2006 08:49 GMT
Hi,

> Thank you. Could you kindly provide "public static void main() " to show
> me how to use it. As you see, I am a little lost here: in the same Java
> file or in the different file? If in the same file, what the file name
> should be?(Test.java or interface.java?) Do I have to make
> doSomethingToArray static?

OK, you have solved this, as I see...

> I still like my previous not-running program, because in yours, as you
> said, Mapper print is "silly"

Well, it is "silly" in your program as well, because, your "PrintMapper"
is no "Mapper" at all, because it "maps" nothing!

> and in the for loop inside
> doSomethingToArray, as[i] = m.map(as[i]) is not needed in my program.

The opposite is true: You need the loop *twice* (or even more, if you
want to implement other Mappers)!

And you have a method "doSomethingToArray" which does not do anything
(except calling another method - which you could do directly).

> My code is more intuitive.

I think, the opposite is true. (But I think there is no way to find out
who is right - we could others let vote for it... ;-)

Ciao,
Ingo
Shawn - 14 Sep 2006 19:33 GMT
/*
For testing passing a method as a method parameter
*/

interface Mapper {
  void map(int[] d);
}

class Demo {
        void doSomethingToArray(Mapper m, int[] aArray) {
                m.map(aArray);
        } //end of method doSomethingToArray

        Mapper squareArray = new Mapper() {
                public void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                a[i] *= a[i];
                        }
                }
        };

        Mapper printArray = new Mapper() {
                public void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                System.out.println(a[i]);
                        }
                }
        };

        private int[] a = new int[3];

        public static void main(String[] args)
        {
                Demo aDemo = new Demo();
                aDemo.a[0] = 1;
                aDemo.a[1] = 2;
                aDemo.a[2] = 3;
               
                aDemo.doSomethingToArray(aDemo.printArray, aDemo.a);
                aDemo.doSomethingToArray(aDemo.squareArray, aDemo.a);
                aDemo.doSomethingToArray(aDemo.printArray, aDemo.a);
        }

} //end of class Demo
Shawn - 14 Sep 2006 19:35 GMT
Following is my code. It runs very well.

Thank you for your any feedback.

/*
For testing passing a method as a method parameter
*/

interface Mapper {
  void map(int[] d);
}

class Demo {
        void doSomethingToArray(Mapper m, int[] aArray) {
                m.map(aArray);
        } //end of method doSomethingToArray

        Mapper squareArray = new Mapper() {
                public void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                a[i] *= a[i];
                        }
                }
        };

        Mapper printArray = new Mapper() {
                public void map(int[] a)
                {
                        for (int i=0; i<a.length; i++)
                        {
                                System.out.println(a[i]);
                        }
                }
        };

        private int[] a = new int[3];

        public static void main(String[] args)
        {
                Demo aDemo = new Demo();
                aDemo.a[0] = 1;
                aDemo.a[1] = 2;
                aDemo.a[2] = 3;
               
                aDemo.doSomethingToArray(aDemo.printArray, aDemo.a);
                aDemo.doSomethingToArray(aDemo.squareArray, aDemo.a);
                aDemo.doSomethingToArray(aDemo.printArray, aDemo.a);
        }

} //end of class Demo
Michael Rauscher - 15 Sep 2006 09:40 GMT
Shawn schrieb:
> Following is my code. It runs very well.
>
> Thank you for your any feedback.

With respect to what Ingo already mentioned, I can't tell you something new.

I expect doSomethingToArray to do something with each element of the
array. It doesn't. Perhaps it's just that my English isn't well enough
to estimate this, but given the body of your method I'd name it
doSomethingWithArray.

That's not nice because can call the Mapper method directly as good as
call it indirectly via doSomethingToArray. Therefore your
doSomethingToArray seems to be rather useless to me.

The next point goes to Ingo, too: You need to iterate over the array in
every mapper.

Regarding the map method: first, I thought it's wrong because it doesn't
seem to map. OTOH doing nothing with the array results in an identity
mapping. But there's one more issue: It's questionable if mapping may
involve changing...

In the end, I'd vote for Ingo's solution ;)

Bye
Michael
Shawn - 15 Sep 2006 14:55 GMT
Thank you all. I don't want to argue the term "Mapper" and what it
suppose to do. I still like my code better.

My code:

    void doSomethingToArray(Mapper m, int[] aArray) {
                m.map(aArray);
        } //end of method doSomethingToArray

         aDemo.doSomethingToArray(aDemo.printArray, aDemo.a);
         aDemo.doSomethingToArray(aDemo.squareArray, aDemo.a);

All the mess(e.g. for loop) are suppressed into the new Mapper(...). At
the above level, it is so clean.

Your code:

  void doSomethingToArray(int[] as, Mapper m) {
    for(int i=0;i<as.length;i++) {
      as[i]=m.map(as[i]);
    }
Ingo R. Homann - 18 Sep 2006 08:31 GMT
Hi,

> Thank you all. I don't want to argue the term "Mapper" and what it
> suppose to do. I still like my code better.

OK, now imagine, you have implemented 10 Mappers and suddenly, you want
to map not only int-Arrays, but also Lists of Integers.

With your approach, you have to change your interface and have to
implement 10 new methods (one for every Mapper-implementation).

With my appraoch, you only have to implement *one* method:

public List<Integer> apply(List<Integer> is, Mapper m) {
  List<Integer> l=new ArrayList<Integer>(is.size());
  for(Integer i:is) {
    l.add(m.map(i));
  }
  return l;
}

Ciao,
Ingo


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.