Разве это не нарушает принцип дизайна интерфейса в c #? - PullRequest
4 голосов
/ 23 февраля 2012

Когда я погуглил, чтобы найти связанные темы об интерфейсе, я нашел это на веб-сайте MSDN:

Например, интерфейс может объявить свойство, которое имеет метод доступа get.Класс, который реализует интерфейс, может объявить одно и то же свойство с помощью метода доступа get и set. от MSDN

Теперь у меня есть сомнения.Когда мы специально упомянули, что свойство должно быть доступно только для чтения (только метод доступа «get» в интерфейсе), почему разрешается также реализовывать метод доступа «set»?

Ответы [ 10 ]

12 голосов
/ 23 февраля 2012

Теперь у меня есть сомнения.Когда мы специально упомянули, что свойство должно быть доступно только для чтения (только метод доступа «get» в интерфейсе), почему разрешается также реализовывать метод доступа «set»?В интерфейсе вы не «указываете, что свойство должно быть доступно только для чтения», а скорее указываете, что контракт определяет «читаемое свойство» с этим конкретным именем и типом.По сути, интерфейс определяет минимальные требования для договора, а не абсолютные требования.

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

3 голосов
/ 23 февраля 2012

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

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

3 голосов
/ 23 февраля 2012

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

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

2 голосов
/ 23 февраля 2012

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

0 голосов
/ 24 февраля 2012

Может быть полезно думать о трех типах вещей: абстрактный ReadableFoo класс (или IReadableFoo интерфейс), наряду с конкретными ImmutableFoo и MutableFoo классами (или IImmutableFoo и * 1006).* интерфейсы).Кто-то, кто получает параметр типа ReadableFoo, сможет прочитать его, но не сможет его установить и не сможет надежно сохранить данные в нем, просто сохранив ссылку.Тот, кто получает параметр ImmutableFoo, сможет надежно сохранить данные, сохранив ссылку, но не сможет их изменить.Тот, кто получает параметр MutableFoo, сможет изменить данные, но не сможет надежно сохранить данные, сохранив ссылку.

0 голосов
/ 23 февраля 2012

То, что сказал Феликс, верно.

Более подробно, интерфейс определяет минимальный набор функциональных возможностей, который должен существовать в любом объекте, определенном как реализующий указанный интерфейс. Это обеспечивает «общий» набор функций среди всех реализаций интерфейса, поэтому вы знаете, что если объект реализует интерфейс, вы можете вызывать X, Y и Z для него. Например, то, что что-то является IDisposable, не означает, что это ВСЕ, что может сделать объект. Фактически это сделало бы интерфейсы довольно бессмысленными, если бы они также определяли максимальный объем функциональности. Это все, что вас волнует, если и когда вы работаете с объектом как реализацией интерфейса; если все, что вам нужно, это IDisposable, вы заботитесь только о вызове Dispose (), независимо от того, какие дополнительные члены может иметь конкретная реализация IDisposable.

Возвращаясь к вашему примеру, интерфейс, определяющий свойство, утверждает, что должен иметь общедоступный метод доступа get. Он не может и не может сказать, что он не может иметь открытый метод доступа; это просто не волнует в любом случае. Установленный метод доступа может быть открытым, внутренним, защищенным, частным или несуществующим; что ожидают потребители интерфейса и, следовательно, что потребуется разработчикам интерфейса, это метод доступа get.

0 голосов
/ 23 февраля 2012
public interface IFoo {
    string Name { get; }
}

class FooImplementation : IFoo {
    public string Name { get; set; }
}

public class FooWorker {
    public void WorkOnFoo(IFoo foo) {
        if (null == foo) throw new ArgumentNullException("foo");
        Console.WriteLine(foo.Name);
    }
}

public class Program {
    public void Main() {
        IFoo foo = new FooImplementation { Name = "Foo" };
        new FooWorker().WorkOnFoo(foo);
    }
}

Что касается FooWorker, параметр foo имеет только аксессор get для свойства Name.

Вероятно, важно помнить, что свойство Name все еще может быть установлено на foo с помощью отражения или приведения.

0 голосов
/ 23 февраля 2012

Интерфейс - это всего лишь декларация о том, как объект должен использоваться потребителями.Это не делает никаких спецификаций о реализации.Там нет противоречий там.

0 голосов
/ 23 февраля 2012

Класс отвечает требованиям интерфейса, все остальное - деталь реализации самого класса. Если вы обращаетесь к объекту через интерфейс, вы увидите только get. Так что нет, это не совсем так, как задумано.

0 голосов
/ 23 февраля 2012

Думайте об интерфейсе как о контракте.Реализаторы обещают по крайней мере соответствовать поведению, определенному в этом контракте, но не ограничиваются им.Интерфейсы позволяют компонентам взаимодействовать, не будучи тесно связанными.Следовательно, реализация может разрешать как get, так и set, но, по крайней мере, должна учитывать get.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...