Java 8中接口的默认方法中使用的阴影变量

Java 8中接口的默认方法中使用的阴影变量,java,oop,java-8,Java,Oop,Java 8,今天我在考虑一个好方法,为不同对象所需的公共功能编写更少的代码 继承可以完成这项工作,但这样类就不能从其他任何人继承,所以我选择了接口 因此,我有一些对象所需的功能接口: public interface Test { String message = "Hello from Interface!"; default void printMessage() { System.out.println(message); } } 然后我可以在任何对象中使用

今天我在考虑一个好方法,为不同对象所需的公共功能编写更少的代码

继承可以完成这项工作,但这样类就不能从其他任何人继承,所以我选择了接口

因此,我有一些对象所需的功能接口:

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

    default void printMessage() {
        System.out.println(message);
    }
}
然后我可以在任何对象中使用它,而不必重写/编写任何代码,而不仅仅是在需要时调用该方法:

public class TestingTest implements Test {

    public String message = "Hello from Class!";

    public TestingTest() {
        printMessage();
    }

    public static void main(String[] args) {
        new TestingTest();
    }
}
它就像一个符咒!但是然后我想,如果我想让这些对象中的一些在不需要的情况下指定不同的消息(可选),那么我想的第一件事是对接口变量进行阴影处理,但它不起作用,默认方法继续使用接口中的变量,而不是类变量(对其进行阴影处理)


当然,一个解决方案是在接口中重载printMessage方法,以便在用户需要指定消息时将消息作为参数接收,但是还有更优雅的方法吗?类似于仅仅在类中声明一条新消息?

接口中的
字符串消息是
静态的(AFAIK)。因此,该计划不起作用

你可能会做一些(丑陋的)事情,比如:

字段没有继承,因此值只能来自可重写的方法,如

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

您需要的是n个类中的功能,如果需要,这些功能也应该是可修改的。 老实说,你的例子有点抽象,因此我的答案也将是抽象的

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");
    }
}
此外,您将拥有一个实现接口并提供消息的类。通过这种方式,您可以对对象进行分组、更改消息、进行更复杂的日志记录,并且实际上可以从外部看到依赖关系

在我看来,你误用了界面。接口提供了从外部调用它的公共方法,但您希望在内部使用它们,就像它们是类的私有功能一样。
只需使用对象即可。

您可以选择,但这种选择比尝试对变量进行阴影处理更糟糕,因为它可能会导致严重的错误。我同意您的看法,反射应该是最后的选择!创建一个默认的
getMessage()
并覆盖它怎么样?即使接口字段是实例字段,也不行。字段不是多态的。您正在滥用接口作为名称空间。接口和“实现”类之间没有真正的继承关系。但是你的例子离现实生活的任务太远了,无法提出替代方案。如果该方法包含更有用的内容,则重载没有问题,但只要不使用多态行为,只需使方法
static
并使用
import static
调用它们而不带前缀。这相当于重载我认为是添加到答案中的方法。@Joop egen:Fields没有继承性??如果访问是公共的或受保护的,字段可以是继承的。我认为他的意思是字段不是多态的,这意味着字段在编译时得到解析,而不像方法在编译时得到解析runtime@Loc你是对的,我的意思是它们不能被推翻,只能被遮蔽;在这里,字段应该完全从计划中删除。
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");
    }
}