9

TL;TD In Java 8, is there a way for an interface default method to access instance variables?

For instance:

public interface Foo{
    default getBazModified(){
       return baz * 2; 
    }
}

public class Bar implements Foo {
   int baz;
   ...
}

I know that sounds like travisty but is there a way to do anything like that in Java 8?

Or is the only way is to have an abstract class that implements Foo, which would have both the instance variable baz declared and have a default implementation of getBazModified()?

Nestor Milyaev
  • 5,845
  • 2
  • 35
  • 51
  • sounds like a use case for method arguments to be implemented – Naman Feb 07 '19 at 16:41
  • nullpointer, could you please elaborate? – Nestor Milyaev Feb 07 '19 at 16:42
  • 1
    i mean a method argument like in `default int getBazModified(int baz){ return baz * 2; }`, what's the challenge there? since anyway you call an instance method which would have its own `baz` value that it can pass on the invocation of this method. – Naman Feb 07 '19 at 16:44
  • Possibly related https://stackoverflow.com/questions/29666676/can-an-interface-hold-any-instance-variables – Naman Feb 07 '19 at 16:48

3 Answers3

16

An interface doesn't "see" its implementation's instance fields. This is not specific to interfaces, any super-type wouldn't know about its sub-types' specific fields (or any member type for that matter).

Your solution in this case is to declare an abstract getter method in the interface and use it to read the property of the subclass:

public interface Foo{
    default int getBazModified(){
       return this.getBaz() * 2; 
    }

    int getBaz();
}

And let the concrete class implement the getter:

public class Bar implements Foo {
   int baz;
   public int getBaz() {return this.baz;}
}
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • 2
    and all that said, there has to be some return type (`int` here) specified for the methods – Naman Feb 07 '19 at 16:43
  • 1
    I've been trying to get a model right and this concrete implementation for the getter whilst declaring it in the interface is perfect. 10000% – George Xavier May 21 '19 at 16:18
4

No. Because variables used inside a default method of an interface have access only to the variables defined inside the interface.

public interface Foo {
int BAZ=1;

default int getBazModified(){
    return BAZ * 2;
  }
}

Remember variables defined inside an interface are public,static and final and they must be initialized.

Now,

public class Bar implements Foo {
  int BAZ = 10;
}

within calling class..

 Foo foo = new Bar();
 System.out.print(foo.getBazModified()); // output: 2

You can only access instance variable inside "Bar" class by overriding default method. Like so,

public class Bar implements Foo {

  int BAZ = 10;

  @Override
  public int getBazModified() {
    return BAZ * 2;
  }
}

And know if,

Foo foo = new Bar();
System.out.print(foo.getBazModified()); // output: 20 (access instance variable)
DASH
  • 124
  • 5
1

Did you try to compile it? The answer is no because the interface doesn't know whether there will even be a field named 'baz' or not.

I know that sounds like travisty but is there a way to do anything like that in Java 8?

Yes. An abstract class. That's literally exactly what abstract classes were designed for.

Michael
  • 41,989
  • 11
  • 82
  • 128