Method does not override package visible method in Eclipse

五迷三道 提交于 2019-12-08 12:59:30

Foo.java:

package foopackage;

public class Foo {
    String getString() {
        return "foo";
    }
}

Bar.java:

package barpackage;

import foopackage.Foo;

public class Bar extends Foo {
    String getString() {
        return "bar";
    }
}

Should do it.

From the Eclipse Help docs:

A package default method is not visible in a different package, and thus cannot be overridden. When this option is enabled, the compiler will signal such scenario either as an error or a warning.

package b;

public class Foo {

    void test() {}

}

And

package a;

import b.Foo;

public class Bar extends Foo {

    void test() {}
}
package a;

public class A {
    // package protected method foo : no visibility modifier
    void foo() {
    }
}

package b;

public class B extends A {
    // although this method has the same signature as A.foo(), it doesn't 
    // override it because A.foo is not visible to B (other package)
    void foo() {
    }
}

An example of why this warning or error is important consider the following example:

package a;

public class Animal { 

    // Note: no visibility modifier therefore package-private
    String makeNoise() {
        return "no noise defined";
    }
}

package b;

import a.Animal;

public class Cat extends Animal {

    // Note: Eclipse will show the warning that it doesn't override
    public String makeNoise() {
        return "meow";
    }

}

package b;

import a.Animal;

public class Dog extends Animal {

    // Note: Eclipse will show the warning that it doesn't override
    public String makeNoise() {
        return "bark";
    }

}

package a;

import java.util.ArrayList;
import java.util.List;

import b.Cat;
import b.Dog;

public class Main {

    public static void main(String[] args) {
        // Make a list of Animals
        List<Animal> animals = new ArrayList<>();
        animals.add(new Cat());
        animals.add(new Dog());

        // Loop through the animals making their noises
        for (Animal animal : animals) {
            System.out.println(animal.makeNoise());
        }
    }

}

Copy paste the whole thing into Eclipse and it will sort out the classes and packages. Then run the Main class. You might expect it to print

meow
bark

But instead it prints

no noise defined
no noise defined

This is confusing behaviour which unexpectedly breaks polymorphism. The reason it does this is the Animal subclasses Cat and Dog have not actually overridden the method makeNoise at all, so when makeNoise is called on an Animal it uses the Animal implementation.

To fix this code add public or protected modifiers to the Animal makeNoise method, then rerun the code it will now work as expected. In this simple example its quite clear what is going on, but in a more complicated situation this behaviour could be extremely confusing and probably incorrect so the warning should be taken seriously.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!