0

In Java, I have only ever defined "method references" Function and BiFunction w/ lambda expressions, like so:

    private static Function<Integer, Boolean> IsEvenFunc =
            (i) -> (i % 2 == 0);
    private static BiFunction<String, Character, Boolean> ByFirstCharFunc =
            (s, c) -> (s.charAt(0) == c.charValue());
    CustomList<Integer> numbers = new CustomList<>();
    numbers.append(9);
    numbers.append(42);
    numbers.append(47);
    System.out.println(numbers.toStringBy(IsEvenFunc));

    CustomList<String> names = new CustomList<>();
    names.append("Joe");
    names.append("Jim");
    names.append("Bob");
    System.out.println(names.toStringBy(ByFirstCharFunc, 'J'));

However, for teaching purposes, if my students don't yet know lambda syntax, is it possible to create these Function and BiFunction methods without lambda expressions?

Something like...?

   private static BiFunction<String s, Character c, Boolean> ByFirstCharFunc
   {
        return s.charAt(0) == c.charValue();
   }
delrocco
  • 495
  • 1
  • 4
  • 23
  • 3
    Use an anonymous inner class. – Ravindra Ranwala Sep 24 '21 at 05:04
  • 1
    Doesn't have to be an anonymous inner class: can be a local class, a top-level class, a nested class, regular class, an enum etc. – Andy Turner Sep 24 '21 at 05:37
  • 2
    On the whole, there is not a good reason to store functional types in fields. Define them as regular methods instead, which you can invoke functionally via a method reference, or directly via a normal method invocation. – Andy Turner Sep 24 '21 at 05:39
  • @AndyTurner, I agree, thank you. I completely forgot about the `::` operator in Java :/ – delrocco Sep 26 '21 at 13:28

2 Answers2

3

You can write a class which implements that interface:

class MatchFirstChar implements Function<String,Boolean> {
  private final char c;
  MatchFirstChar(char c) {
    this.c = c;
  }
  Boolean apply(String s) {
    return s.charAt(0) == c;
  } 
}

and then use it:

System.out.println(names.toStringBy(new MatchFirstChar('J')));

This is more verbose than any of the other ways of doing this, but I think it introduces the minimum of new concepts.

tgdavies
  • 10,307
  • 4
  • 35
  • 40
2

You could always just define it as a regular function/method like this:

private static boolean IsEven(int i){
    return i % 2 == 0;
}

private static boolean FirstChar(String s, char c){
    return s.charAt(0) == c;
}
Wellerman
  • 846
  • 4
  • 14
  • Yea, and then pass the method name w/ the `::` operator right? I guess I so rarely use the `::` operator in Java that I forgot about it... Thx. – delrocco Sep 24 '21 at 05:11
  • Yes exactly. Here's a more detailed explanation of it. https://stackoverflow.com/questions/20001427/double-colon-operator-in-java-8 – Wellerman Sep 24 '21 at 05:14
  • @delrocco Note that `::` is used as a part of a _method reference_. If your students don't yet know lambda expressions, then I'm not sure method references will make much more sense. Perhaps you should be using an anonymous class instead. – Slaw Sep 24 '21 at 05:30
  • @Slaw, thx. They do understand the concept of a "function pointer" and do work in C++ as well. However, in Java, the only way I knew how to do a "method reference" was by making one of those `Function`s or `BiFunction`s with the lambda syntax. I forgot completely about just using a regular method and passing w/ the `::` operator. Obviously the operator is different in C++, so never remember that in Java :/ My fault. – delrocco Sep 26 '21 at 13:25
  • 1
    @delrocco Yeah, it can get confusing with all the different languages using different terms, or even the same term to mean something else. In Java, a "functional interface" is an interface that has only one abstract method. Every interface in the `java.util.function` package is an example of a "functional interface". A "lambda expression" is one way to declare an implementation of a "functional interface". For example, `a -> System.out.println(a)` is an implementation of a functional interface whose abstract method accepts one argument and returns nothing (e.g. `java.util.function.Consumer`). – Slaw Sep 26 '21 at 18:28
  • 1
    And a "method reference" is another way to declare an implementation of a "functional interface". Using the same example as the "lambda expression" in my previous comment, the "method reference" version would look like `System.out::println`. But whether you use a named class, an anonymous class, a lambda expression, or a method reference, you're still literally defining an implementation of an interface. An actual instance of that interface is created at run-time. In other words, there's no proper first-class "function" type in Java (not sure how C++ function pointers actually work). – Slaw Sep 26 '21 at 18:34