Подтвердить что ты не робот

Интерфейс: сеттер без Getter

Недавно я столкнулся с интерфейсом, который определил только такой сеттер:

public interface IAggregationView
{
   DataTable SetSiteData { set; }
}

Я запросил это, и считается, что это один из методов, рекомендованных Microsoft для разработки WebPart (для SharePoint). Фактически этот пример непосредственно скопирован из их примеров.

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

Мне интересно, может ли кто-нибудь объяснить выгоду только наличия сеттера, почему Microsoft может предложить его в этом случае, и действительно ли это хороший шаблон?

4b9b3361

Ответ 1

Есть два сценария, которые я могу видеть, где это может быть разумным:

  • невозможно получить значение, например пароль; однако я бы заменил это на метод void SetPassword(string), лично
  • API, для которого он предназначен, не требует когда-либо считывать значение, и он ограничен только для раскрытия минимально необходимого API

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

Re: "Я не понимаю, почему кто-то должен иметь возможность установить значение, а затем не сможет прочитать его снова" - по той же причине, однако, можно утверждать, что кто-то, задающий значение, уже знает значение (они устанавливают его), поэтому для этого не требуется требование.

Но да; очень необычно иметь свойство set-only.

Ответ 2

Роль get и set в свойствах интерфейса несколько отличается от роли в классах.

public interface IAggregationView
{
   DataTable SetSiteData { set; }
}

class AggregationViewImp : IAggregationView
{
   public DataTable SetSiteData { get; set; }  // perfectly OK
}

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

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

Как следствие, вы даже не можете указать свойство "только для чтения" в интерфейсах. Только "по крайней мере доступ для чтения".

interface IFoo
{
    int Id { get;  }
}

class Foo : IFoo
{
    public int Id { get; set; }  // protected/private set is OK too
}

Ответ 3

Я могу представить, как использовать его для (ручной) инъекции зависимостей. У класса может потребоваться, чтобы коллаборатор ввел его, только он использует только внутренне. Конечно, обычно можно было бы сделать это в конструкторе класса, но могут быть случаи, когда вы захотите изменить соавтор во время выполнения.

Ответ 4

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

Интерфейс - это всего лишь средство для объявления группы "атомарно необходимых" операций (например, если вам нужно вызвать метод A, вам нужно будет прочитать свойство B и установить свойство C).

Как всегда, это зависит.

Ответ 5

В моем опыте такие интерфейсы возникают из-за какой-то особой необходимости, а не по архитектурным причинам. Например, в приложениях ASP.NET люди иногда вызывают генерируемый тип Global.asax из такого интерфейса, когда они хотят поддерживать глобальное состояние. Кто-то может создать значение инициализации в отдельной части приложения и должен опубликовать его в глобальном месте.

Мне обычно нравится заменять свойство set-only на метод SetXxx и проверять, что он вызывается не более одного раза. Таким образом, я четко навязываю "стиль инициализации", который намного меньше запаха (imho).

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