Как сделать частичную виртуальную собственность? - PullRequest
6 голосов
/ 15 декабря 2010

Дизайн - в идеальном мире

У меня есть один абстрактный базовый класс A со свойством Value и два производных класса W и R. Всегда можно прочитать Value (и метод всегда один и тот же - чтение сохраненного значения), поэтому я бы поставил getter непосредственно к А.

Однако запись в Value не всегда возможна, и, таким образом, W и R. W также предоставляет установщик, а R - нет - он просто полагается на функции, полученные из A.

Проблема в том, что, что бы я ни пытался, я не могу воплотить такой дизайн в C #. Я не могу переопределить свойство Value в W, потому что в базовом классе нет сеттера (и его нет, потому что добавление сеттера в базовый класс означает, что он также «утечет» в R).

Реальность - безобразный обходной путь (не читайте)

Я добавил сеттер в A, который выбрасывает исключение. В W я переопределяю setter, а в R я ничего не делаю.

Это ужасно из-за замысла, потому что setter в R общедоступен и потому что теперь такой код компилируется:

R reader;
reader.Value = 5;

Вопрос

Итак, как создать свойство только с геттером в базовом классе и добавить сеттер в производный класс?

История

Поскольку всегда есть хотя бы одна любопытная душа, я объясняю - эти классы являются держателями данных / менеджерами. Класс R является «держателем» динамических данных - он вычисляет значение по заданной формуле (аналогично классу Lazy Eval). Большая часть вещей распространена среди W и R - фильтрация значений, отправка уведомлений и так далее. Единственная разница в том, что в R вы не можете установить значение напрямую, потому что формула односторонняя (аналогично конвертеру WPF с определенным только одним методом, Преобразовать).

Решение

Спасибо Марку, я решил эту проблему, вот код:

  abstract class A {
      public int Value { get { return ... } }
  }

  class R : A { }

  class W : A {
      new public int Value {
          get { return base.Value; }
          set { .... }
      }
  }

Разница с версией Marc заключается в отсутствии сеттера в базовом классе (в этом и заключался весь вопрос), разница в моем обходном пути заключается в том, что свойство затеняется, а не переопределяется. Маленькая, но важная часть.

Спасибо, Марк, за просветление: -).

1 Ответ

7 голосов
/ 15 декабря 2010
abstract class A {
    public int Value {get; protected set;}
}
class R : A { }
class W : A {
    new public int Value {
        get { return base.Value; }
        set { base.Value = value; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...