0

I know this is a really rare thing to happen, but it happened to me today for real, after I made a refactor of a function called "progress" to "setProgress". I have this code creating an object of an anonymous subtype of SwingWorker, and in its "doInBackground" method I have another function call to a custom type of my own, which is also anonymously typed. Both types, it turns out, have the exact same function called "setProgress" defined. Note: SwingWorkerEx is just a custom subtype of SwingWorker.

new SwingWorkerEx<Void, Void>() {
          @Override
          protected Void doInBackground() throws Exception {
            final SwingWorkerEx self = this;
            lazyNode.loadForce(_dao, new ProgressListener() {
              @Override
              public void setProgress(@Nullable ProgressOperation operation, int percent) {
                setProgress(percent);
              }
            });
            return null;
          }

The error I get is:

setProgress (ProgressOperation, int) in ... cannot be applied to (int)

Java obviously thinks I'm trying to refer to the innermost class's setProgress methods, and thinks I got the parameters wrong. Luckily the function signatures didn't match or I'd have got infinite recursion to deal with later! I'm trying to disambiguate, but can't. I even tried this solution: How to refer to enclosing anonymous class instance in Java?, doing the following:

 protected Void doInBackground() throws Exception {
            final SwingWorkerEx self = this;

And

@Override
              public void setProgress(@Nullable ProgressOperation operation, int percent) {
                self.setProgress(percent);
              }

But the subtlety of access modifiers caught me out. In particular, Java complained:

'setProgress(int)' has protected access in 'javax.swing.SwingWorker'

Some Notes

I'm just going to give one of the classes a name, but I'm wondering if it actually is theoretically possible to solve this in Java? If not, it's an interesting limitation.

One more thing I did think of, was to extract the SwingWorker's function as a Function type and then pass this function down to the nested anonymous class, but alas- it's of void type! And making it Void (capital V) is just a workaround, not a solution. The definition of a nominal class IMO is a better solution anyway.

Another thing that didn't work, was overriding the setProgress function in the anonymous SwingWorkerEx subtype:

@Override
public void setProgress(int percent){super.setProgress(percent);}

This is because the function is final in SwingWorker.

Colm Bhandal
  • 3,343
  • 2
  • 18
  • 29

1 Answers1

0

For anyone facing this challenge, here is a workaround. I won't accept this though as it's not a solution. Perhaps there is no solution.

In the anonymous subclass of SwingWorkerEx, define this function:

public void setProgressSuper(int percent){super.setProgress(percent);}

Then call it in the anonymous implementation of ProgressListener, within the doInBackground function:

@Override
              public void setProgress(@Nullable ProgressOperation operation, int percent) {
                setProgressSuper(percent);
              }
            });

Putting it all together:

  new SwingWorkerEx<Void, Void>() {

      //Need this as a workaround to accessing the protected function in the anonymous ProgressListener class below
      public void setProgressSuper(int percent){super.setProgress(percent);}

      @Override
      protected Void doInBackground() throws Exception {      
        lazyNode.loadForce(_dao, new ProgressListener() {

          @Override
          public void setProgress(@Nullable ProgressOperation operation, int percent) {
            setProgressSuper(percent);
          }
        });
        return null;
      }
...
Colm Bhandal
  • 3,343
  • 2
  • 18
  • 29