Непубличные члены для интерфейсов C # [закрыто]

В C # при реализации интерфейса все члены неявно являются открытыми. Разве не было бы лучше, если бы мы могли указать модификатор доступности ( protected, internalза исключением, privateконечно), или вместо этого мы должны просто использовать абстрактный класс?

20.08.2008 08:14:06
Вы можете скрыть интерфейс от API, если вы реализуете его явно.
epitka 25.08.2010 20:11:48
9 ОТВЕТОВ

Не имеет смысла. Интерфейс - это договор с общественностью, что вы поддерживаете эти методы и свойства. Палка с абстрактными классами.

5
20.08.2008 08:15:40
«Внутренний» модификатор доступа может показаться совершенно полезным для интерфейсов; Интерфейс, который имеет такой модификатор на любом из его элементов, может быть реализован только кодом внутри сборки, в которой он объявлен, но может использоваться кодом где угодно. Я вижу множество применений для этого.
supercat 12.01.2012 23:58:21
Я не думаю, что интерфейсы предназначены для использования в качестве строго типизированных руководящих принципов или в качестве основы для кода в тех же сборках. Я считаю, что их главная цель - «взаимодействие» с внешним миром.
Ishmaeel 17.01.2012 10:04:44
Предположим, что сборка определяет BankCheckingAccount, CreditUnionCheckingAccount, BankSavingsAccount и CreditUnionSavingsAccount. Банковские счета имеют функции, отсутствующие на счетах кредитных союзов, и наоборот. У чековых счетов есть особенности, которых нет в сберегательных счетах и ​​наоборот. Было бы полезно иметь типы для проверки счетов, сберегательных счетов, банковских счетов и счетов кредитных союзов, но можно использовать только абстрактные классы для двух из этих четырех. Если наследование абстрактных классов было ограничено одной и той же сборкой ...
supercat 17.01.2012 15:52:10
... можно быть уверенным, что CheckingAccount является либо BankCheckingAccount, либо CreditUnionCheckingAccount и не является JoeHackerPhonyCheckingAccount. Было бы полезно иметь возможность предоставить аналогичные гарантии для интерфейса IBankAccount (реализуемого BankCheckingAccount и BankSavingsAccount) или интерфейса ICreditUnionAccount (реализуемого CreditUnionCheckingAccount и CreditUnionSavingsAccount). [Конечно, нельзя доверять реальную финансовую информацию безопасности на уровне класса - это всего лишь аналогия].
supercat 17.01.2012 15:55:13
«Интерфейс - это договор с общественностью, что вы поддерживаете эти методы и свойства» - я не согласен с этим, я бы сказал, что интерфейс - это (или должен быть) договор с исполнителем. И я должен быть в состоянии обеспечить реализацию определенных частных методов и свойств.
Gavin Williams 8.02.2019 06:34:17

Интерфейсы не имеют модификаторов доступа в своих методах, оставляя их открытыми для любого подходящего модификатора доступа. Это имеет цель: оно позволяет другим типам определять, какие методы и свойства доступны для объекта, следующего за интерфейсом. Предоставление им защищенных / внутренних средств доступа нарушает назначение интерфейса.

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

1
20.08.2008 08:22:50
позволение другим (читать внешним) типам выводить, какие методы и свойства доступны для объекта, является желанным выбором? Я бы сказал, что объект должен быть в состоянии решить, что должно быть доступно для внешнего мира.
nawfal 24.09.2012 11:13:34
Точно, nawfal - и интерфейс - это контракт, а не объект. Интерфейсы должны использоваться для описания доступного поведения в отличие от определения деталей реализации.
Jon Limjap 24.09.2012 17:11:49
Джон, сегодня я понял свой контракт. Не просто контракт, а скорее «публичная спецификация для всего мира». Я подверг сомнению этот принцип, но когда слово ppl выражается словами, они звучат как «почему члены интерфейса общедоступны?» Ответы на которые часто встречаются, являются разновидностями «такого рода контракта». @ Джон Скит говорит здесь, что это так, потому что это так. Вот еще одно следствие наличия непубличных членов интерфейса.
nawfal 24.09.2012 19:08:07
Но теперь мне интересно, почему определение элемента не может быть в самом интерфейсе частным, общедоступным и т. Д. Я до сих пор думал, что интерфейсы существуют также для обеспечения разработки класса (который включает в себя общедоступные, защищенные, приватные и т. Д. Члены) и все же чувствую, что что-то должно быть чтобы обеспечить это.
nawfal 24.09.2012 19:09:22
Поздний ответ, но представьте себе частных участников в публичном интерфейсе. Как класс должен реализовывать все элементы интерфейса, если он даже не мог знать, что они там? Конечно аналогично другим модификаторам. Как отмечено в принятом ответе, вы можете ограничить доступ к самому интерфейсу, предотвращая любые попытки даже выполнить контракт, когда вы не должны этого делать. Так сказать, закрытый / защищенный / внутренний интерфейс был бы как контракт, о котором другие не знают. Взаимодействие с непубличными членами было бы похоже на неясный договор, который невозможно было бы полностью реализовать.
user3613916 27.06.2014 10:37:55

Я знаком с Java, а не с C #, но с какой стати вам нужен частный член в интерфейсе? Он не может иметь никакой реализации и будет невидим для реализации классов, поэтому будет бесполезен. Существуют интерфейсы для определения поведения. Если вам нужно поведение по умолчанию, чем использовать абстрактный класс.

0
20.08.2008 08:17:08
внутренний член имеет смысл правильно?
nawfal 24.09.2012 11:04:15
Я думаю, что можно объявить весь интерфейс (в отличие от отдельного метода) внутренним. Это имеет больше смысла.
Jon Limjap 24.09.2012 17:12:47
@JonLimjap это возможно, и единственное преимущество, которое он делает, это то, что он скрывает интерфейс от внешних сборок, как и ожидалось, но они все еще требуют, чтобы его члены были публичными (что странно), что означает, что эти публичные свойства и методы видны внешнему миру! !
nawfal 24.09.2012 18:51:21

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

Внутренние члены для интерфейса вне его декларирующей сборки были бы бессмысленными, равно как и защищенные члены для интерфейса вне его декларирующего внешнего класса.

Цель интерфейса - описать контракт между типом реализации и пользователями интерфейса. Внешние абоненты не будут заботиться и не должны заботиться о реализации, для чего предназначены внутренние и защищенные участники.

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

36
26.08.2017 13:31:20
что вы подразумеваете под "пользователями этого интерфейса"? Так что, когда вы создаете переменную, скажем IMyInterface someVar; А потом как-нибудь использовать VAR?
PositiveGuy 8.07.2010 17:56:24
Также я могу добавить, что интерфейсы навязывают структуру / общность структуре вашего приложения (классы внутри), что является предметом объятий, даже если вы не выставляете интерфейсы внешним клиентам ... правильно ??
PositiveGuy 8.07.2010 20:32:03
Я думаю, что для интерфейсов полезно иметь internalчленов. Если сборка Foo может содержать интерфейс IWoozleс internalчленами, и если она содержит пять реализаций IWoozle, код в любом месте может передавать экземпляры IWoozleи использовать его открытые члены, но код, который получил IWoozleбы, будет знать, что он реализован в сборке Foo. Рассмотрим, например, гипотетический интерфейс IImmutableWoozle. Возможно, что реализации могут не иметь общий базовый тип, но если реализации вне Foo не может быть, то ...
supercat 13.01.2012 00:06:22
... код в Foo, или который верил, что Foo не сделает ничего противного, мог знать, что IImmutableWoozleне будет какой-то дурацкой изменчивой реализацией.
supercat 13.01.2012 00:07:35
В этом случае вы можете создать внутренний интерфейс, IInternalWoozleкоторый реализует, IWoozleи любой код в Foo, который использует любой IWoozleможет проверить, IInternalWoozleтакже реализован ли для того, чтобы добраться до внутренних членов. .NET Framework делает это местами.
Mark Cidade 13.01.2012 19:43:46

Вы можете скрыть реализацию интерфейса, явно указав имя интерфейса перед именем метода:

public interface IInterface {
    public void Method();
}

public class A : IInterface {
    public void IInterface.Method() {
        // Do something
    }
}

public class Program {
    public static void Main() {
        A o = new A();
        o.Method(); // Will not compile
        ((IInterface)o).Method(); // Will compile
    }
}
20
20.04.2017 07:39:25
Просто комментарий: в настоящее время вы не можете использовать publicмодификатор в элементе интерфейса или явно реализованном методе интерфейса. Например, чтобы ваш код работал с .NET 4.5, просто publicудалите оба файла.
Andrew 5.07.2015 03:34:29
Андрей, о каких двух публиках ты говоришь?
Kyle Delaney 26.01.2017 18:51:45
Почему бы не o.Method()скомпилировать? Может кто-нибудь объяснить это? Почему указание имени интерфейса скрывает реализацию интерфейса?
Kyle Delaney 26.01.2017 18:54:03
Кайл. Эта нотация (реализация метода с именем интерфейса) называется явной реализацией интерфейса, и я думаю, ее цель - скрыть метод от вызываемого извне (кроме явного приведения и последующего вызова). Это очень полезно для некоторых случаев. Например, базовый класс может выполнять одноразовую операцию при реализации метода интерфейса. Если метод виден внешним абонентам, они могут вызывать метод более одного раза и нарушать рабочее состояние базового класса.
Xtro 27.10.2017 13:24:08

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

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

Либо используйте абстрактный базовый класс, либо (если это возможно и практично) метод внутреннего расширения интерфейса .

2
23.05.2017 12:09:36
Если бы нужно было объявить открытый абстрактный класс, все члены и конструкторы которого были бы internal, то внешний код мог бы получать из сборочных ссылок на вещи этого типа и передавать такие ссылки обратно в методы сборки, сохраняя при этом безопасность типов, без внешний код должен знать что-либо о рассматриваемом классе. К сожалению, такой подход будет работать только в том случае, если ни одному из конкретных производных абстрактного класса не потребуется наследовать от чего-либо, что не происходит от этого абстрактного класса.
supercat 31.05.2013 23:55:59
Интерфейс, который содержал внутренние члены, если бы такая вещь была разрешена, был бы во многом похож на вышеупомянутый абстрактный класс, но с тем преимуществом, что он мог быть реализован классами, которые были получены из классов, которые этого не делали.
supercat 31.05.2013 23:56:48

Вы можете скрыть почти весь код, реализованный интерфейсами, для внешних сборок.

interface IVehicle
{
    void Drive();
    void Steer();
    void UseHook();
}
abstract class Vehicle  // :IVehicle  // Try it and see!
{
    /// <summary>
    /// Consuming classes are not required to implement this method.
    /// </summary>
    protected virtual void Hook()
    {
        return;
    }
}
class Car : Vehicle, IVehicle
{
    protected override void Hook()  // you must use keyword "override"
    {
        Console.WriteLine(" Car.Hook(): Uses abstracted method.");
    }
    #region IVehicle Members

    public void Drive()
    {
        Console.WriteLine(" Car.Drive(): Uses a tires and a motor.");
    }

    public void Steer()
    {
        Console.WriteLine(" Car.Steer(): Uses a steering wheel.");
    }
    /// <summary>
    /// This code is duplicated in implementing classes.  Hmm.
    /// </summary>
    void IVehicle.UseHook()
    {
        this.Hook();
    }

    #endregion
}
class Airplane : Vehicle, IVehicle
{
    protected override void Hook()  // you must use keyword "override"
    {
        Console.WriteLine(" Airplane.Hook(): Uses abstracted method.");
    }
    #region IVehicle Members

    public void Drive()
    {
        Console.WriteLine(" Airplane.Drive(): Uses wings and a motor.");
    }

    public void Steer()
    {
        Console.WriteLine(" Airplane.Steer(): Uses a control stick.");
    }
    /// <summary>
    /// This code is duplicated in implementing classes.  Hmm.
    /// </summary>
    void IVehicle.UseHook()
    {
        this.Hook();
    }

    #endregion
}

Это проверит код.

class Program
{
    static void Main(string[] args)
    {
        Car car = new Car();
        IVehicle contract = (IVehicle)car;
        UseContract(contract);  // This line is identical...
        Airplane airplane = new Airplane();
        contract = (IVehicle)airplane;
        UseContract(contract);  // ...to the line above!
    }

    private static void UseContract(IVehicle contract)
    {
        // Try typing these 3 lines yourself, watch IDE behavior.
        contract.Drive();
        contract.Steer();
        contract.UseHook();
        Console.WriteLine("Press any key to continue...");
        Console.ReadLine();
    }
}
2
8.08.2017 20:34:54

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

Это самая обсуждаемая тема, позвольте мне опубликовать два превосходных ответа, которые я нашел на SO, когда этот вопрос всплыл в моей голове.

Этот ответ дает пример того, как бессмысленно иметь неоднородные спецификаторы доступа для членов интерфейса в производных классах. Код всегда лучше технических описаний.

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

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

3
23.05.2017 12:25:42

По моему мнению, это нарушает инкапсуляцию. Я должен реализовать методы как публичные, затем я реализую интерфейс. Я не вижу причин, чтобы заставить public в классе, который реализует интерфейс. (C #)

0
13.03.2017 02:06:10