简体   繁体   English

Java - 向接口实现添加方法

[英]Java - Adding methods to interface implementation

I'll use an easy example for the sake of the question.为了这个问题,我将使用一个简单的例子。

If I have an Interface say Animal which is like如果我有一个InterfaceAnimal就像

public interface Animal {
    void jump();
}

And I'm creating an object of the interface on the go, like我正在旅途中创建界面的对象,例如

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. 
    }
}

Now, I added the sleep() method to the interface implementation and want that method to be callable from the place where I'm calling cat.jump() .现在,我将sleep()方法添加到接口实现中,并希望可以从我调用cat.jump()的位置调用该方法。 That is what I want.这就是我想要的。 I see that throws an error and I do understand because the object is of type Animal and Animal does not have the sleep() method.我看到这会引发错误,我确实理解,因为该对象属于Animal类型,而Animal没有sleep()方法。

If I do not want to add a new method to the interface , in that case, what other options do I have to be able to call a method that I created in interface implementation?如果我不想向interface添加新方法,在这种情况下,还有哪些其他选项可以调用我在接口实现中创建的方法?

The problem is that you didn't understand what it is to program for the interface.问题是你不明白为接口编程是什么。 I believe you are thinking that it is a rule that you have created and must follow.我相信你在想这是你创造的规则,必须遵守。 It is not.它不是。 It is something to understand why it exists and to do it when necessary.了解它为什么存在并在必要时这样做是一件很重要的事情。

You must declare a variable as the interface if you only need what is in the interface.如果您只需要接口中的内容,则必须将变量声明为接口。 If you need what is in the concrete class then you must declare the concrete class.如果您需要具体类中的内容,则必须声明具体类。

Casting or something else is adopting a mistake to fix the first mistake.铸造或其他东西正在采用错误来修复第一个错误。

Interfaces should be used to segregate responsibilities.应该使用接口来分离职责。 You program to interface so that what will receive the object can only access what is in that type.您对接口进行编程,以便接收对象的内容只能访问该类型的内容。 It is purposeful that it does not allow other members of the concrete object to access.它是有目的的,不允许具体对象的其他成员访问。 If you used the interface, that code does not know what is not in the interface.如果你使用了接口,那代码不知道接口中没有什么。

Do you still want to call didSomething () and be through an interface?你还想通过一个接口调用didSomething ()吗? You have two possibilities:你有两种可能:

  • Create a new interface with this method and there you can declare the variable with the type of the interface, access the desired method, and you will be programming for the interface.使用此方法创建一个新接口,您可以在那里声明具有接口类型的变量,访问所需的方法,然后您将为该接口编程。 I consider this the most appropriate, but it may not be, in an abstract example like this, everything is possible;我认为这是最合适的,但可能不是,在这样一个抽象的例子中,一切皆有可能;
  • Place the method in the existing interface and you will be able to access it.将方法放在现有接口中,您将能够访问它。 It may not be what you want, but it is a possibility.这可能不是你想要的,但它是一种可能性。 I don't know what you want, the names used don't indicate what it should be.我不知道你想要什么,使用的名称并没有表明它应该是什么。

In fact, although it is useful to see how it works, programming for interface in something as simple as that is of no practical use.事实上,虽然了解它是如何工作的很有用,但是用这么简单的方式为接口编程并没有实际用处。 It is useful to use this technique when you have complex systems, which will need maintenance and flexibility to change the implementation without having to change the contract.当您拥有复杂的系统时使用此技术很有用,这些系统需要维护和灵活性来更改实现而无需更改合同。

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();
    }
}

If you want to call a method that's not in the interface, then you can't use the interface to make the call, you have to use the class.如果要调用一个不在接口中的方法,那么就不能使用接口进行调用,必须使用类。

Since the class is anonymous, you can't use the class.由于该类是匿名的,因此您不能使用该类。

Make a real named class, instead of using anonymous classes, eg create a class Cat .创建一个真正的命名类,而不是使用匿名类,例如创建一个class Cat

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

When you use the following syntax:当您使用以下语法时:

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

you are not creating an instance of the Superclass (in this case, Animal ).不是在创建超类的实例(在本例中为Animal )。 Rather, you are creating an instance of some unspecified Subclass of the Superclass.相反,您正在创建超类的某个未指定子类的实例。 The only reason why you are able to store it in a reference variable of the Superclass is because of polymorphism .您能够将它存储在超类的引用变量中的唯一原因是多态性

You should only be using anonymous inner classes, as opposed to creating and instantiating an actual class, when you want to override a single method in the Superclass and only intend to use the new class once.当您想覆盖超类中的单个方法并且只打算使用新类一次时,您应该只使用匿名内部类,而不是创建和实例化实际类。 If you are creating a new method, as you did here with the sleep method, it is better practice to create an actual class.如果您正在创建一个新方法,就像您在此处使用sleep方法所做的那样,最好创建一个实际的类。

With that being said, if you must use an anonymous inner class and you are using Java 10 or later, you do have the option of using local variable type inference .话虽如此,如果您必须使用匿名内部类并且您使用的是 Java 10 或更高版本,则您可以选择使用局部变量类型推断 This is accomplished via the var keyword.这是通过var关键字完成的。

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

In you use the var keyword instead, the Java compiler will infer the anonymous type of the Subclass, which will include all of the methods in the Subclass.如果您使用var关键字,Java 编译器将推断子类的匿名类型,它将包括子类中的所有方法。 This does have its limitations - you'll lose access to new methods if you pass the object as a parameter - but it will work otherwise.这确实有其局限性 - 如果您将对象作为参数传递,您将无法访问新方法 - 但否则它会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM