【问题标题】:Java - Adding methods to interface implementationJava - 向接口实现添加方法
【发布时间】:2021-01-11 08:01:29
【问题描述】:

为了这个问题,我将使用一个简单的例子。

如果我有一个 InterfaceAnimal 这就像

public interface Animal {
    void jump();
}

我正在创建一个接口对象,比如

public class Main {
    public static void main(String[] args) {
        
        Animal cat = new Animal() {
            @Override
            public void jump() {
                System.out.println("The cat jumped");
            }

            public void sleep() {
                System.out.println("The cat slept");
            }
        };
        cat.jump(); 
        cat.sleep(); // cannot do that. 
    }
}

现在,我将sleep() 方法添加到接口实现中,并希望可以从我调用cat.jump() 的位置调用该方法。这就是我想要的。我看到这会引发错误,我确实理解,因为该对象的类型为 Animal 并且 Animal 没有 sleep() 方法。

如果我不想向interface 添加新方法,在这种情况下,我还需要哪些其他选项才能调用我在接口实现中创建的方法?

【问题讨论】:

  • 为什么不直接创建Catimplements Animal 类?
  • Animal(){} 的实例是一个匿名对象,只能在匿名对象范围内访问,在此之后声明的任何内容都可以在没有反射的情况下访问

标签: java methods interface implements


【解决方案1】:

问题是你不明白为接口编程是什么。我相信您认为这是您制定的并且必须遵循的规则。它不是。了解它为什么存在并在必要时执行它是一件很重要的事情。

如果您只需要接口中的内容,则必须将变量声明为接口。如果您需要具体类中的内容,则必须声明具体类。

铸造或其他东西是采用错误来纠正第一个错误。

应该使用接口来分离职责。您对接口进行编程,以便接收对象的内容只能访问该类型的内容。它是有目的的,它不允许具体对象的其他成员访问。如果你使用了接口,那代码不知道接口中没有什么。

您还想调用didSomething () 并通过接口吗?你有两种可能:

  • 用这个方法创建一个新的接口,在那里你可以用接口的类型声明变量,访问所需的方法,你将为接口编程。我认为这是最合适的,但可能不是,在这样一个抽象的例子中,一切皆有可能;
  • 将方法放在现有界面中,您将能够访问它。它可能不是你想要的,但它是一种可能性。我不知道你想要什么,使用的名称并不表示它应该是什么。

事实上,虽然看看它是如何工作的很有用,但是以如此简单的方式为接口编程是没有实际用处的。当您拥有复杂的系统时使用此技术很有用,这需要维护和灵活性来更改实现而无需更改合同。

interface Something {
    void doSomething();
}

interface Otherthing {
    void doOtherthing();
}

class Whatever implements Something, Otherthing {
    public void doSomething() {
       System.out.println("Do something !");
    }     
    public void doOtherthing() {
       System.out.println("Do otherthing !");
    }
}

class Test {
    public static void main(String[] arguments) {
        Something s = new Whatever();
        s.doSomething();
        Otherthing w = new Whatever(); 
        w.doOtherthing();
    }
}

【讨论】:

    【解决方案2】:

    如果要调用接口中没有的方法,则不能使用接口进行调用,必须使用类。

    由于该类是匿名的,因此您不能使用该类。

    创建一个真正的命名类,而不是使用匿名类,例如创建一个class Cat

    class Cat implements Animal {
        // methods from anonymous class here
    }
    
    Cat cat = new Cat();
    cat.jump();
    cat.sleep(); // you can do this now
    

    【讨论】:

      【解决方案3】:

      当您使用以下语法时:

      SuperClass anonymousInstance = new SuperClass() {
         /*Code here*/
      }
      

      没有创建超类的实例(在本例中为Animal)。相反,您正在创建超类的某些未指定子类的实例。您能够将其存储在超类的引用变量中的唯一原因是polymorphism

      当您想要覆盖超类中的单个方法并且只打算使用新类一次时,您应该只使用匿名内部类,而不是创建和实例化实际类。如果您正在创建一个新方法,就像您在此处使用 sleep 方法所做的那样,最好创建一个实际的类。

      话虽如此,如果您必须使用匿名内部类并且您使用的是 Java 10 或更高版本,则可以选择使用local variable type inference。这是通过var 关键字完成的。

      var anonymousInstance = new SuperClass() {
         /*Code here*/
      }
      

      如果您改用var 关键字,Java 编译器将推断子类的匿名类型,这将包括子类中的所有方法。这确实有其局限性 - 如果您将对象作为参数传递,您将无法访问新方法 - 但否则它会起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-01
        • 2017-11-29
        • 2020-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多