С#: наследование наследования геттеров/сеттеров
У меня есть набор интерфейсов, которые используются в тесном взаимодействии с определенным изменчивым объектом.
Многим пользователям объекта требуется только возможность считывать значения из объекта, а затем только несколько свойств. Чтобы избежать загрязнения пространства имен (проще intellisense) и чтобы понять смысл использования, я хотел бы иметь небольшой базовый интерфейс, который предоставляет только несколько "ключевых" свойств только для чтения.
Однако почти все реализации будут поддерживать полный интерфейс, который включает в себя изменчивость.
К сожалению, я столкнулся с дорожным блоком, выражающим эту концепцию в С#:
interface IBasicProps {
public int Priority { get; }
public string Name {get;}
//... whatever
}
interface IBasicPropsWriteable:IBasicProps {
public int Priority { set; } //warning CS0108: [...] hides inherited member [...]
public string Name { set; }
//... whatever
}
Я, конечно же, не собирался скрывать каких-либо членов, так что нехорошо!
Конечно, я могу решить это, используя методы просто отлично, но какой правильный выбор? Я бы хотел, чтобы "основной" интерфейс был как можно мал, даже если разделение интерфейсов не имеет никакой цели, кроме передачи намерений. С раздельными интерфейсами просто очевидно, какие методы не собираются делать никакого обновления, и это делает код написания немного понятнее (не говоря уже о том, что для простого простого случая достаточно простых статических одноэлементных прошивок достаточно простого).
Я бы хотел избежать любых абстрактных классов и тому подобного; они делают повторное выполнение или быстрые одноцелевые прокладки все более сложными и труднодоступными.
Итак, идеи?
Ответы
Ответ 1
Метод, скрывающийся в интерфейсе, не так близок; Я бы пошел с чем-то вроде:
interface IBasicProps {
int Priority { get; }
string Name {get;}
//... whatever
}
interface IBasicPropsWriteable:IBasicProps {
new int Priority { get; set; }
new string Name { get; set; }
//... whatever
}
class Foo : IBasicPropsWriteable {
public int Priority {get;set;}
public string Name {get;set;}
/* optional
int IBasicProps.Priority {get {return Priority;}}
string IBasicProps.Name {get {return Name;}}
*/
}
Ответ 2
Если ваша цель состоит в том, чтобы сделать ее более ясной, если разрешено чтение или запись, я бы использовал отдельные методы getter и setter, а не свойства.
interface IBasicProps {
int GetPriority();
string GetName();
//... whatever
}
interface IBasicPropsWriteable:IBasicProps {
void SetPriority(int priority);
void SetName(string name);
//... whatever
}
Ответ 3
Одним из способов может быть просто пропустить наследование интерфейсов. Сделайте один интерфейс только для чтения и один только для записи и при необходимости выполните:
interface IBasicPropsReadable {
int Priority { get; }
string Name { get; }
}
interface IBasicPropsWriteable {
int Priority { set; }
string Name { set; }
}
class SomeClassReadWrite : IBasicPropsReadable, IBasicPropsWriteable {
int Priority { get; set; }
string Name { get; set; }
}
class SomeClassReadOnly : IBasicPropsReadable {
int Priority { get; }
string Name { get; }
}
Ответ 4
Вы можете оставить интерфейсы несвязанными и просто обеспечить, чтобы ваш класс реализовал оба интерфейса. Ведь интерфейсы просто определяют контракт, и контракты не обязательно должны быть связаны. Похоже, это просто оптимизация для вас, когда кодирование позволяет записывать один из другого, поэтому вам нужно указать только один интерфейс.
public interface IBasicProps
{
int Priority { get; }
string Name {get;}
//... whatever
}
public interface IBasicPropsWriteable
{
int Priority { get; set; }
string Name { get; set; }
//... whatever
}
public class Foo : IBasicProps, IBasicPropsWriteable
{
public int Priority { get; set; }
public string Name { get; set; }
// whatever
}
Если вам действительно нужна оптимизация, вы можете создать еще один интерфейс, который вытекает из обоих, и ваши классы реализуют это.
public interface IBasicPropsAll : IBasicProps, IBasicPropsWriteable { }
public class Foo : IBasicPropsAll
{
public int Priority { get; set; }
public string Name { get; set; }
// whatever
}