Rafael R. S. Robles
Rafael R. S. Robles

Reputation: 897

Shadowing variable used in a default method of an interface in Java 8

Today I was thinking about a nice way to write less code for a common functionality that is required for different objects.

Inheritance can do the job but then the classes won't be able to inherit from anyone else, so I chose Interfaces.

So I have my interface with the functionality I will need for some objects:

public interface Test {
    String message = "Hello from Interface!";

    default void printMessage() {
        System.out.println(message);
    }
}

And then I can use it in any object without having to override/write any code more than just simply calling the method when needed:

public class TestingTest implements Test {

    public String message = "Hello from Class!";

    public TestingTest() {
        printMessage();
    }

    public static void main(String[] args) {
        new TestingTest();
    }
}

It works like a charm! But... Then I thought, what if I want some of those objects to specify a different message without being required (optional), well first thing I thought was to shadow the interface variable, but it doesn't work, the default method keeps using the variable from the interface instead of the class variable (which shadowed it).

A solution of course would be to overload the printMessage method in the interface so it recieves the message as a parameter for when the user requires to specify the message, but is there any more elegant way? Something like simply just declaring a new message in the class?

Upvotes: 4

Views: 768

Answers (2)

Shryne
Shryne

Reputation: 121

What you want is a functionality in n classes that should also be modifiable, if needed. To be honest, your example is a little bit abstract and thus my answer will be abstract, too.

public interface Test {
    void printMessage();

    default void printMessage(String message) {
        System.out.println(message);
    }
}

public class TestingTest {
    private final test;

    public TestingTest(Test test) {
        this.test = test;
    }

    public void someMethod() {
        test.printMessage("Hello from class");
    }
}

Additionally, you would have a class that implements the interface and offers the message. This way you could group your objects, change the message, make more complex logging and you would actually see the dependency from outside.

In my opinion, you are misusing the interface. An interface offers public methods to call it from outside, but you want to use them inside like they were private functionalities for the class. Just use objects instead.

Upvotes: 0

Joop Eggen
Joop Eggen

Reputation: 109593

The String message in the interface is static (AFAIK). So that scheme does not work.

You might do something (ugly) as:

default void printMessage(String... messages) {
    if (messages.length == 0) {
        messages = new String[] { "arrgg" };
    }
    System.out.println(messages[0]);
}

Fields have no inheritance, so the value can only stem from an overridable method like

public String message() { return "..."; }

Upvotes: 3

Related Questions