0

My original code looked like this:

SpecificEntity result = broker.changeSpecificEntity ( myTestKey , myTestData ) ;

"broker" is an (interface/implementation facade) with several methods (create, change, remove, etc) for each of many entity types.

I want to implement a generic version of the code so I don't have to repeat myself. There is more code than shown here, but the rest is already generic.

This is what we have so far.

public < K extends Key , D extends Data > D changeAnyEntity ( final K testKey, final D testData, BiFunction<K, D, D> brokerMethod ) 
{
    return brokerMethod.apply ( testKey , testData ) ;
}

Now I need to invoke a generic method, (e.g., changeAnyEntity) for each of the methods under test.

SpecificEntity result = changeAnyEntity ( myTestKey , myTestData , myBrokerFuncion )

I have not yet figured out how to define / create "myBrokerFunction"

snaydjoW
  • 1
  • 2
  • Frequently the answer to "how do I pass a method" is to declare a method that accepts an interface that includes the signature of the method that you want to call. Ideally, it's a @FunctionalInterface, to make it easy to pass lambdas. – Andy Thomas Jan 01 '23 at 22:32
  • Does this answer your question? [Pass Method as Parameter](https://stackoverflow.com/questions/2186931/). – Andy Thomas Jan 01 '23 at 22:34
  • I re-wrote the question to clarify where I am at. The help provided so far moved me along, but I'm still stuck on how to tie it all together. – snaydjoW Jan 02 '23 at 04:17

2 Answers2

0

Create an interface with a single method accepting your wanted arguments and returning the type you need. Then you can use that interface as a parameter type, and you can avoid all unnecessary casting inside your generic method. The reason for making it generic is to avoid "knowing" about all individual child types after all

@FunctionalInterface
interface BrokerFun<KK, DD> {
    DD changeEntity(KK key, DD data);
}

public < K extends Key , D extends Data > boolean changeAnything (
        final K testKey,
        final D testData,
        BrokerFun<K, D> brokerFun
) {
    try {
        D result = brokerFun.changeEntity(testKey,testData);
        return isEqualCriticalFields(result, testData);
    } catch ( final Exception e ) {
        return false ;
    }
}

EDIT(Adding a BiFunction solution)

Alternatively you can use the BiFunction interface like this

public < K extends Key , D extends Data > boolean changeAnything (
        final K testKey,
        final D testData,
        BiFunction<K, D, D> brokerFun
) {
    try {
        D result = brokerFun.apply(testKey,testData);
        return isEqualCriticalFields(result, testData);
    } catch ( final Exception e ) {
        return false ;
    }
}
Klitos G.
  • 806
  • 5
  • 14
  • Thanks -- I'll take another look -- my comment above (apparently with lousy markdown) shows where I'm currently stuck. – snaydjoW Jan 02 '23 at 02:11
  • Ok I see you wanna use BiFunction, let me add to my answer – Klitos G. Jan 02 '23 at 02:15
  • I have added a BiFunction solution. You don't need to declare another generic type for your Interface, I think that's where you are getting confused. The BiFunction or the declared Interface should use the types of the other arguments, K and D are the only generic types you need. This way you will make sure that this function cannot be called with incompatible types – Klitos G. Jan 02 '23 at 02:22
  • You're right about me being confused, but it looks as though you've done what I was aiming for (not that I care whether I use BiFunction or not -- I just want something that works and doesn't smell ;-) ) It's getting late (for January 1st) so I'll probably continue tomorrow. I think I'm still missing the part where I supply the broker function changeAnything ( myTestKey , myTestData , myBrokerFunction ) where originally the broker function was "broker.changeEntity" – snaydjoW Jan 02 '23 at 02:49
0

Finally . . . ignoring try/catch logic

final BiFunction < SpecificEntityKey , SpecificEntityData , SpecificEntityData >
brokerMethod = ( k , d ) -> { myBroker.changeSpecificEntity ( k , d , null ) ; return d ; } ;
snaydjoW
  • 1
  • 2
  • and of course, by defining my own interface instead of using BiFunction, I was able to include the necessary throws declaration and everything works perfectly. Thank you both. I can't @ both of you for some reason! @AndyThomas – snaydjoW Jan 02 '23 at 18:46
  • Thank you both. I can't @ both of you for some reason! @KlitosG – snaydjoW Jan 02 '23 at 18:48