Почему мы должны объявлять методы интерфейса общедоступными?

Когда я реализую interface метод, я вынужден сделать его public методом.

У нас могут быть случаи, когда мы хотим использовать либо default (например, в случае доступа в одном пакете), либо protected.

Кто-нибудь может объяснить причину этого ограничения?


person Vishnu    schedule 08.03.2012    source источник
comment
Если вам нужны защищенные и частные члены или статические методы и нестатические поля, вы можете использовать abstract class   -  person Peter Lawrey    schedule 08.03.2012


Ответы (5)


Интерфейсы предназначены для определения общедоступного API типа - и только этого, а не его реализации. Таким образом, любой метод (или статический член), который вы определяете в интерфейсе, по определению является public.

Поскольку интерфейс не может содержать какой-либо конкретной реализации, невозможно вызвать какие-либо методы-члены изнутри. И объявление таких методов, но оставление вызовов подклассам или полностью несвязанным клиентам будет означать, что определение вашего типа является неполным и хрупким. Вот почему, если вам нужно определить защищенные члены или члены доступа к пакету, вы можете сделать это в абстрактном классе (который также может содержать реализацию).

person Péter Török    schedule 08.03.2012
comment
Я думаю, что это правильный ответ, но в основном это окольный способ сказать, потому что это то, чего хотели люди, занимающиеся Java. Вы также можете привести вполне разумные аргументы в пользу наличия защищенных методов (package-private может быть немного сложнее обосновать). Но у вас определенно не может быть частных методов, поскольку они никогда не наследуются. Я предполагаю, что вместо того, чтобы говорить об этом подмножестве видимости, и вот почему это, но не то, они подумали, что было бы проще просто сказать, что это единственная видимость, которую вы получаете. - person yshavit; 08.03.2012
comment
@yshavit, я попытался подумать о почему люди, занимающиеся Java, хотели, чтобы все было так. Одна часть информации, которая была упущена выше, заключается в том, что они добавили интерфейсы к языку специально, потому что они хотели запретить множественное наследование и все проблемы, которые это вызвало в C ++. - person Péter Török; 08.03.2012
comment
@yshavit, были бы заинтересованы в любых вполне разумных аргументах в пользу наличия защищенных методов :-) - person Péter Török; 08.03.2012
comment
+1 для иллюстрации концептуальной разницы между интерфейсами и абстрактными классами. - person pap; 08.03.2012
comment
Технически методы в любом случае являются общедоступными - вы всегда можете получить ссылку на интерфейс, если у вас есть ссылка на объект. - person Simon Richter; 08.03.2012
comment
ну это просто зависит от языка. в C # интерфейсы всегда общедоступны. - person Nahum; 08.03.2012
comment
@ PéterTörök Сразу же я мог представить себе интерфейс, который может собирать и сообщать какую-либо информацию, но который также имеет методы обратного вызова с конкретными обещаниями на стороне вызывающего (например, чтобы все они вызывались в каком-то конкретном потоке) . Было бы неплохо, если бы вы могли пометить их как защищенные, чтобы только пакет, определяющий интерфейс, мог получить к ним доступ (плюс, конечно, сам класс). Или, возможно, вы не хотите, чтобы люди могли getFoo() напрямую, а только через метод (определенный где-то в этом пакете), который оборачивает его в какой-то Bar перед его возвратом. И Т. Д. - person yshavit; 08.03.2012
comment
@yshavit, ИМХО все это легко решается с помощью двух отдельных интерфейсов, один из которых - package private. - person Péter Török; 14.05.2012
comment
@ PéterTörök. Даже если вы это сделаете, конкретный класс, реализующий интерфейс, должен будет сделать эти методы общедоступными. Таким образом, методы по-прежнему будут частью общедоступного API, но не будут организованы как часть частного интерфейса пакета ... почти худшее из обоих миров, поскольку вы должны опубликовать этот концептуально скрытый метод, но не контекст, в котором это определено. - person yshavit; 14.05.2012
comment
@yshavit, только если вы программируете для конкретных классов, а не интерфейсов. В противном случае вы публикуете экземпляр PublicInterface для некоторого клиента (возможно, в другом пакете) и экземпляр PackagePrivateInterface для некоторого другого клиента (в том же пакете). Никого не волнует, являются ли это одним и тем же физическим объектом. - person Péter Török; 15.05.2012
comment
И объявление таких методов, но оставление вызовов подклассам или полностью несвязанным клиентам будет означать, что определение вашего типа является неполным и хрупким. - Не могли бы вы уточнить, как предоставление доступа к такому методу несвязанным клиентам оставляет тип неполным? @ PéterTörök - person sindhu_sp; 28.05.2020
comment
В Java Спецификатор общего доступа указывает, что интерфейс может использоваться любым классом в любом пакете. Если вы не укажете, что интерфейс является общедоступным, то ваш интерфейс будет доступен только для классов, определенных в том же пакете, что и интерфейс. - person O_K; 16.06.2020

Возможно, это даст некоторые ответы.

Насколько мне известно, вы используете interfaces, чтобы позволить людям, не относящимся к вашему коду, взаимодействовать с вашим кодом. Для этого вам нужно определить свои методы public.

Если вы хотите заставить кого-то переопределить данный набор частных методов, вы можете объявить абстрактный класс с серией абстрактных защищенных методов.

person npinti    schedule 08.03.2012
comment
абстрактные частные методы ... вы имели в виду абстрактные защищенные методы? - person BoltClock; 08.03.2012
comment
@ npinti-ну проще говоря! - person Vishnu; 08.03.2012
comment
@BoltClock: Да, вы правы. Исправлено спасибо :) - person npinti; 08.03.2012
comment
Или абстрактные методы области видимости по умолчанию (пакет) - person Amir Pashazadeh; 08.03.2012
comment
Однако Джошуа Блох настоятельно рекомендует использовать интерфейсы как -типы- и использовать эти типы для ссылки на объекты. Это хорошая идея, но она развивает два способа концептуализации интерфейсов: как механизм для использования определяемых пользователем типов таким образом, чтобы не мешать одиночному наследованию; и как контракт API. Поскольку у нас есть эти два, я согласен, что было бы ОЧЕНЬ хорошо, если бы нам не нужно было делать методы интерфейса общедоступными, чтобы сохранить инкапсулированными те UDT, которые мы не хотели экспортировать. - person scottb; 09.06.2013

Интерфейс - это контракт, согласно которому класс, который его реализует, будет иметь методы в интерфейсе. Интерфейс используется, чтобы показать остальной части программы, что у этого класса есть методы и что они могут быть вызваны.

person nist    schedule 08.03.2012
comment
Да, но интерфейсы тоже типы. Иногда программисты хотят использовать созданные ими типы, не экспортируя их как часть API. Вот где принуждение к публичному использованию методов интерфейса раздражает. - person scottb; 09.06.2013

РЕДАКТИРОВАТЬ: Этот ответ предназначен для реализации интерфейса C #. В этом случае Java сценарий аналогичен тому, что синтаксический анализатор хочет, чтобы ключевое слово public было упомянуто в интерфейсе, что неявно выполняется в C #.

Методы интерфейса в C # неявно открыты, поскольку интерфейс - это контракт, предназначенный для использования другими классами. Кроме того, вы должны объявить эти методы общедоступными, а не статическими, при реализации интерфейса.

interface IStorable
{
     void Read( );
     void Write(object obj);
}

Обратите внимание, что объявления методов IStorable для Read( ) и Write( ) не включают модификаторы доступа (public, protected ..). Фактически, предоставление модификатора доступа приводит к ошибке компиляции.

class Document : IStorable
{
     public void Read( )
     {
         //
     }
     public void Write(object obj)
     {
         //
     }
}

Просто подумайте об интерфейсах как о контрактах, которые должны быть реализованы как public

person Jerric Lyns John    schedule 24.03.2014
comment
В Java вам действительно нужно указать ключевое слово public. - person Groo; 02.09.2014
comment
@Groo Мое плохое, возможно, я не увидел тег, связанный с вопросом. Я говорил о случае в C #, я упомяну об этом в редакции. - person Jerric Lyns John; 02.09.2014

  1. Если мы помечаем метод интерфейса как частный, реализующий класс не увидит метод и не сможет его переопределить.

  2. Если мы отметим метод интерфейса как защищенный, реализующий класс не увидит метод, если он не находится в том же пакете, что и интерфейс.

  3. Если мы отметим метод интерфейса без какого-либо модификатора доступа, реализующий класс
    не увидит метод, если он не находится в том же
    пакете, что и интерфейс.

person user1929905    schedule 14.06.2016