В некоторых случаях описанный вами шаблон оправдан. Например, может быть полезно иметь абстрактный класс MaybeMutableFoo
, из которого производные подтипы MutableFoo
и ImmutableFoo
. Все три класса включают свойство IsMutable
и методы AsMutable()
, AsNewMutable()
и AsImmutable()
.
В этой ситуации было бы вполне уместно, чтобы MaybeMutableFoo
предоставил свойство чтения-записи, если его контракт явно указывает, что установщик может не работать, если IsMutable
не вернет true. Объект с полем типа MaybeMutableFoo
, который содержит экземпляр ImmutableFoo
, может быть полностью доволен этим экземпляром до тех пор, пока ему не понадобится запись в него, после чего он заменит поле на объект, возвращенный через AsMutable()
, а затем использовать его в качестве изменяемого foo (он знал бы, что он изменчив, поскольку он только что заменил его). Включение в MaybeMutableFoo
установщика позволит избежать необходимости выполнять любые будущие типовые трансляции на поле после того, как оно было сделано для ссылки на изменяемый экземпляр.
Лучший способ разрешить такой шаблон - избегать реализации виртуальных или абстрактных свойств, а вместо этого реализовывать не виртуальные свойства, чьи методы получения и установки устанавливаются в цепочку с виртуальными или абстрактными методами. Если один имеет базовый класс
public class MaybeMutableFoo
{
public string Foo {get {return Foo_get();} set {Foo_set(value);}
protected abstract string Foo_get();
protected abstract void Foo_set(string value};
}
тогда производный класс ImmutableFoo
может объявить:
new public string Foo {get {return Foo_get();}
, чтобы сделать его свойство Foo
доступным только для чтения, не мешая возможности переопределения кода для абстрактных методов Foo_get()
и Foo_set()
. Обратите внимание, что замена только для чтения Foo
не меняет поведение свойства get; версия только для чтения объединяет тот же метод базового класса, что и свойство базового класса. Поступая таким образом, вы гарантируете наличие одной точки исправления для изменения метода получения свойства и одной точки для изменения метода установки, и эти точки исправления не изменятся, даже если само свойство будет переопределено.