Не публичные пользователи для интерфейсов С#

В С#, когда вы реализуете интерфейс, все члены общедоступны по умолчанию. Считаете ли вы, что лучше, если мы сможем указать модификатор доступности (защищенный, внутренний, за исключением частного, конечно) или лучше использовать вместо него абстрактный класс?

Ответ 1

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

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

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

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

Ответ 2

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

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
    }
}

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

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

Ответ 6

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

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

Ответ 7

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

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();
    }
}

Ответ 8

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

Ответ 9

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