Изменение видимости метода 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
,
У меня есть следующие вопросы:
- Является
default
вinterface
отличный отdefault
видимость, которая предоставляется, когда модификатор доступа не применяется? - Если это отличается, то как это отличается?
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
,
Короче говоря: прочитайте о принципе подстановки Лискова, чтобы понять, почему "убирать" публику не очень хорошая идея - она полностью независима от смешивания "видимости, защищенной пакетами по умолчанию" и ключевого слова по умолчанию в интерфейсах.