7

I have an interface that defines a setter/getter using java 8 default methods, but I am getting an error when attempting to wire it up in Spring. I really want to avoid using abstract class and I don't want to duplicate the code. Here is what I am doing:

public interface MyProcessor
{
  public static final WeakHashMap<Function1D, Integer> paramMap = new WeakHashMap<>();

  default void setParam(int param)
  {
        paramMap.put(this, param);
  }

  default int getParam()
  {
      return paramMap.get(this);
  } 

  default double doSomthingWithParam(double x)
  {  
          return doSomething() * getParam();
  } 

  double doSomething();
 }


public class MyProcessorImp extends SomeClass implements MyProcessor
{
    double doSomething() {....}
 } 

  <bean class="....MyProcessorImp"> <property name="param" value="3"/></bean>

Bean property 'param' is not writable or has an invalid setter method.

Saul
  • 91
  • 1
  • 5
  • 3
    Why do you want to avoid using an abstract class? Inheriting implementation is exactly what abstract classes are for. Also, did you really mean for `paramMap` to be `static`? Note that this means there is only one `paramMap` which is shared between all instances of all classes that implement the interface. – Jesper May 05 '15 at 20:40
  • yes, i did mean for it to be static, its the only way it can work. i had a feeling a response to my question would be a question such as that, i don't want to get into the programming model now, but just take it as a valid reason, and read up on java 8 default methods, ask yourself why it was added as new architectural feature, and then you might understand my reason for it. – Saul May 06 '15 at 13:10
  • The main reason that default methods were added in Java 8 is to make it possible to add methods to interfaces without breaking backward compatibility - not as a replacement for abstract classes. – Jesper May 06 '15 at 18:41
  • 2
    good. so now you might have an idea why I need to do this. Actually, you should note that while you believe that this is the main reason, in actuality, this is a symptom of an model that does not work well. I'd like to think of the change as less of a hack for backwards compatibility that you imply but more of an architectural change to allow for a richer programing model, which in-turn addresses the issue that Java was unable to deal with before. Either way, I'm really looking for ideas to have this specific setup working, not for socratic debates about its usage. – Saul May 06 '15 at 20:54
  • In my case there is no place for abstract class until Java supports multiple-inheritance subclassing. I have classes such as XxxSupport, and want to mix-in their getters and setters into existing classes. – Askar Kalykov Jul 10 '15 at 06:55

1 Answers1

3

In my own projects, I get the implementor to supply me with the dependency supplied by spring's DI container.

Reworking the code above, this would look like this:

public interface MyProcessor {

  // get the implementor to get the hash map
  WeakHashMap<Function1D, Integer> getParamMap();

  default double doSomthingWithParam(double x) {  
    return doSomething() * getParam();
  } 

  // uses the implementor's getParamMap() to get params
  default int getParam() {
    return getParamMap().get(this);
  } 

  double doSomething();
}

public class MyProcessorImp extends SomeClass implements MyProcessor {

  final WeakHashMap<Function1D, Integer> paramMap = new WeakHashMap<>();

  void setParam(int param) {
    paramMap.put(this, param);
  }

  @Override WeakHashMap<Function1D, Integer> getParamMap() {
    return paramMap;
  }

  @Override double doSomething() { 
    // elided 
  }
} 
Philippe
  • 4,088
  • 4
  • 44
  • 49