Изменение видимости метода Java по умолчанию 8

У меня есть class (Сказать FOO) и у него есть метод с default видимость, как показано ниже:

void sayHi() {}

Теперь, если переопределить этот метод в расширении класса, я не могу уменьшить его видимость. Так что я могу использовать только default или же public,

public class MyClassTest extends FOO {
    @Override
    // Or I can use public void sayHi()
    void sayHi() {
        System.out.println("Overriden sayHi");
    }
}

Теперь, если я напишу интерфейс в Java 8 с методом по умолчанию, как показано ниже:

public interface InterfaceX {

    // Java-8 defalu method
    default String printName() {
        System.out.println("Interface1 default metod");
        return "Interface1 default metod";
    }
}

Теперь, если я переопределю этот метод в классе, он должен скомпилироваться, если видимость метода переопределить keep default,

public class Java8InterfaceTest implements InterfaceX{
    @Override
     void printHello() {
        System.out.println("Printing..!");
        Interface1.super.printName();
    }
 }

Это говорит

Невозможно уменьшить видимость унаследованного метода от InterfaceX

Я уже знаю, что каждый метод в interface в public по умолчанию, но в приведенном выше примере мы используем default который я считаю одним из access modifier в java,

У меня есть следующие вопросы:

  1. Является default в interface отличный от default видимость, которая предоставляется, когда модификатор доступа не применяется?
  2. Если это отличается, то как это отличается?

3 ответа

Решение

default не имеет ничего общего с видимостью по умолчанию. default Метод в интерфейсе - это метод, имеющий реализацию по умолчанию в интерфейсе.

Видимость этого метода все еще public,

Поэтому метод, реализованный в вашем Java8InterfaceTest класс должен иметь public видимость:

public void printHello() {
    ...
}

Я думаю, что если вы напишите свой интерфейс как:

interface Test {
    default public void go() {

    }
}

это имело бы смысл. default методы все еще public; ничего общего с видимостью по умолчанию.

Другие ответы хорошо подчеркивают этот "синтаксический" недостаток в вашем предположении о том, что дефолт является "видимостью".

Но за этим стоит отдельная проблема: концептуальная проблема заключается в том, что не следует уменьшать наглядность методов.

Имейте в виду: общедоступный "API" класса или интерфейса объявляет контракт для работы с клиентским кодом. Как: имея метод eat() на базовый класс / интерфейс Animal,

Все дело в том, что разные подклассы / реализации могут обеспечить свою собственную реализацию eat(), Так что вы можете иметь:

Animal whatever = ...
whatever.eat();

И ни на что ... на самом деле создает (может быть Cat, Dog, Unicorn) - это действительно для вызова whatever.eat(),

Ваша идея состоит в том, чтобы сказать: я хочу "спрятаться" eat() для определенного подкласса Donkey, Если бы вы могли это сделать - внезапно приведенный выше код может оказаться недействительным. Так как whatever.eat() больше не является действительным вызовом, когда whatever случается, пример Donkey,

Короче говоря: прочитайте о принципе подстановки Лискова, чтобы понять, почему "убирать" публику не очень хорошая идея - она ​​полностью независима от смешивания "видимости, защищенной пакетами по умолчанию" и ключевого слова по умолчанию в интерфейсах.

Другие вопросы по тегам