0

I can't seem to think in java. What I want is a single function that takes two functions as arguments, and executes one of them, checks for a cache miss, and executes the second one if there was. I can't figure out how to do this in java without rewriting all the function definitions in subclasses/interface implementations.

so, how would I write something like

def(cacheFun, diskFun){
  String astring = cacheFun.call()
  if(!isBlank(astring)){
    return astring
  } else {
    return diskFun.call()
  }
}

in java?

What I don't want is a bunch of anonymous classes that implement the function that I want under an interface (at least not in the way that I'm thinking about it). There are a lot of functions that handle the cache in different ways. This means that the superclass would have to have a function for each way of caching.

public String getUsingWayOne(){
  String retval = WayOneCacheClass.new.execute()
  if(retval is not empty){
    return retval
  } else {
    retval = WayOneDiskClass.new.execute()
    return retval
  }
}

and repeat this for all the different ways there are of caching

Is there a solved way of doing this in java? Please do not suggest caching libraries. The purpose of this question isn't to actually cache things, but to learn to write code the "right" (java) way.

Peter Klipfel
  • 4,958
  • 5
  • 29
  • 44
  • 1
    As Java doesn't (yet) have lambda functions, I think you'll have to do something equivalent to a "bunch of anonymous classes". Or use reflection... – Oliver Charlesworth Aug 13 '13 at 21:29
  • 1
    This is the closest you get to passing functions as argument in java: http://stackoverflow.com/a/4685606/726239 – Shaunak Aug 13 '13 at 21:33
  • The only way to "take a function as an argument" in Java currently is, indeed, to pass around those anonymous classes. – Louis Wasserman Aug 13 '13 at 21:48

2 Answers2

1

There are several ways of doing something like you are talking about in Java, but I think the main thing is that you shouldn't think about passing around function pointers. In Java, the key thing is that you are always using thinking in terms of Objects, and Interfaces and Inheritance are your friends.

It sounds like you have a lot of implementations which are all children of a common super class, and you want a method which can test one method to see if a cache hit occurred and call another method if a miss occurred. To do this, my first inclination would be to have the implementations inherit from an Abstract Class. Abstract classes are like Interfaces, in that they define an interface, but they also can define common methods that don't need to be implemented by each child class. So, you could write something like this:

public abstract class FunCache {
  public String getValue() {
    String result = cacheFun();
    if (result == null) {
      result = diskFun();
    }
    return result;
  }

  abstract public String cacheFun();
  abstract public String diskFun();
}

class FirstImplementation extends FunCache {
  public String cacheFun() {
    // implementation!
  }

  public String diskFun() {
    // implementation!
  }
}

// some other code that wants to use it
FunCache fc = new FirstImplementation();
String value = fc.getValue();
seanmk
  • 1,934
  • 15
  • 28
0

In java, you can do (a transliteration of your code):

public String getUsingWayOne(){
   String retval = WayOneCacheClass.execute();
   if (retval != null && !retval.isEmpty()) {
       return retval;
   return WayOneDiskClass.execute();
}

Note that I've made the execute() method static, because it's obviously stateless.


Or you can set up the two ways in an instance (without knowing more, this is what I'd do):

public interface Cacher {
    execute();
}

public class TwoWayCacher {
    private final Cacher one;
    private final Cacher two;

    public TwoWayCacher (Cacher one, Cacher two) {
        this.one = one;
        this.two = two;
    }

    public String get() {
       String retval = one.execute();
       if (retval != null && !retval.isEmpty()) {
           return retval;
       return two.execute();
    }
}

then to use:

TwoWayCacher cacher = new TwoWayCacher(new WayOneCacher(), new WayTwoCacher());

String result = cacher.get();
Patrick
  • 1,717
  • 7
  • 21
  • 28
Bohemian
  • 412,405
  • 93
  • 575
  • 722