简体   繁体   中英

@Override, with default methods in interfaces

I've been reading through some questions here on SO concerning the use of @Override in Java. (eg this one on override and this one on default methods , and obviously the documentations ) However, I am still confused.

I was taught to always use and implement an interface when all behaviour in that interface needed to be used by a class. I get that. But as I was taught, you would do something like this (partially taken from the docs):

public interface TimeClient {
    void setTime(int hour, int minute, int second);
}

Which is then implemented by a class.

public class TestSimpleTimeClient implements TimeClient {
    public static void main(String[] args) {
    }

    @Override
    public void setTime(int hour, int minute, int second) {
         System.out.println(hour + " " + minute + " " +second);
    }
}

The thing that bugs me is the implementation of the method in the interface. It doesn't do anything, it's only declared as a method that take arguments but doesn't do anything else. Then you take that method and Override it in a class that implements that interface.

I understand that this is a way to "force" classes to implement a method but I don't see how this is useful in some specific use cases.

Let's say I have an interface that's implemented by a couple of classes. I want most of these classes to share the same implementation of the method, but not all. The logical, and character-efficient way would be to have a way to say: these classes take the default method in the interface, but these classes override the default method. How would I go about doing that? Should the one that overrides the method only implement it, whereas the ones that simply use the default method as a whole extend it? And what if you only want this behaviour for a specific method in an interface?

The thing that bugs me is the implementation of the method in the interface. It doesn't do anything, it's only declared as a method that take arguments but doesn't do anything else.

That is not an "implementation of the method in the interface". That's just an interface method declaration. In programming, terminology matters. Interfaces tend to be devoid of any implementations. (Unless you are talking about the default interface methods of Java 8, but from the rest of your question it is unclear whether you are aware of their existence.)

I understand that this is a way to "force" classes to implement a class

A class cannot implement a class. A class extends a class. But a class implements an interface. In programming, terminology matters a lot.

It is not just a way to force classes to provide an implementation. It is also a way for callers to be able to invoke an interface method without having to know anything about the class that implements it.

but I don't see how this is useful in some specific use cases.

Well, take for example the Collection<T> interface, and the contains() method, which is implemented by a myriad of classes, among which ArrayList<T> , LinkedList<T> , HashSet<T> , BoundedBlockingQueue<T> , and so on, and so forth. Your code may look like this:

boolean hasPekingese( Collection<Animal> animals )
{
    return animals.contains( AllOfMyAnimals.PEKINGESE );
}

Note how the hasPekingese() method does not have to know the exact class that is implementing Collection<Animal> . Which means that you may invoke hasPekingese() from a class which keeps its animals in an ArrayList<Animal> , and you may also invoke hasPekingese() from a class which keeps its animals in a BoundedBlockingQueue<Animal> . The method hasPekingese() does not know, and does not care.

Let's say I have an interface that's shared by a couple of classes.

It is unclear what you mean by "shared". Do you mean "implemented"? In programming, terminology is of paramount importance.

I want most of these classes to share the same implementation of the method, but not all. The logical, and character-efficient way would be to have a way to say: these classes take the default method in the interface, but these classes override the default method. How would I go about doing that?

There are many ways to go about that, the most common being to have some of these classes extend some common base class, which provides the common implementation of your method, so that the derived classes inherit this method, so they do not have to implement it. The rest of the classes do not extend that common base class, so each one of them has to provide its own implementations of that method.

Should the one that overrides the method only implement it, whereas the ones that simply use the default method as a whole extend it?

That's not clear. Also, please do not call it a "default method", because as of Java 8 "default method" is a term that has a very specific meaning, and although it is related to this discussion, it is different from the sense in which you are using it.

And what if you only want this behaviour for a specific method in an interface?

If a derived class wants the method to work differently, it may re-override it. Or, you may have two different base classes, one which implements the method in a certain way, and another which implements it differently, so half of your derived classes extend the first base class, while the other half of your derived classes extend the second base class.

Interfaces are like APIs. When some provider give you interface like List you don't think about if it is an ArrayList or other implementation, you just know what you can do with this object. Why? Because when you give an interface, you can change the implementation later, and don't worry that other part of code, that is using object through interface, will need changes.

I suppose that you think about things that should plug some behaviour to current class. These things can be called Traits in other programming languages, in another you have multiple inheritance. If you want some implemented logic that is propagated to your classes, you should use abstract classes in java with proper hierarchic. Remember that you can expand classes with inheritance or composition ( open-closed principle ).

Default methods in Interfaces (Java 8) can be tricky, because they cannot change state of the object. They might be some stubs or mathematics equation that only work with local and static context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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