Как запечатать переопределенное свойство
-
30-09-2019 - |
Вопрос
Предположим, у меня есть пара явно надуманных C # классами, как это:
public abstract class Foo {
public abstract int[] LegalValues { get; }
public virtual bool IsValueLegal(int val) {
return Array.IndexOf(LegalValues, val) >= 0;
}
}
и это:
public class Bar : Foo {
static int[] _legalValues = new int[] { 0, 1 }; // whatever
public sealed override int[] LegalValues
{ get { return _legalValues; } }
public sealed override bool IsValueLegal(int val)
{ return base.IsValueLegal(val); }
}
Как мне это сделать в #? Очевидный код для свойств:
[<Sealed>]
override this.LegalValues with get() = // ...
[<Sealed>]
override this.IsValueLegal value = // ...
Запускает ошибку, поскольку герметичныйattribute, по-видимому, не может быть применен к членам. Конечно, я могу запечатать весь класс и тем самым запечатать всех членов, но (и это Действительно важно Но) в том, что у меня есть цель соответствовать существующей подписи класса точно И базовый класс имеет другие виртуальные / абстрактные члены, которые должны быть, в идеале, остаются переопределенными.
Решение
В настоящее время существует несколько ограничений для поддержки F # для OO, поэтому вы, как правило, не должны ожидать, что сможет создать иерархию классов F #, которая идентична произвольному иерархию классов классов C #. Насколько я знаю, нет способа переопределить и запечатать виртуальный метод.
Другие советы
Похоже, F # определяет Герметичный атрибут Определяется своим свойством атрибутетаргет, установленным только на класс, его, вероятно, невозможно уплотнить членов.
Это, вероятно Ok, поскольку наследование и переопределение функций, как правило, менее идиоматичны в F #, чем C #. Я не думаю, что вы действительно можете получить то, что вы хотите, не переписывая в большем количестве идиомов F #. Начните с этого:
type foo =
| Bar
| Baz
| Qux
with
member this.LegalValues =
match this with
| Bar -> [0; 1]
| Qux -> [-1; 0; 1]
| Baz -> [0 .. 10 ]
member this.IsValueLegal value =
match this with
| Baz -> value >= 0 && value <= 10
| _ -> List.exists (fun x -> x = value) (this.LegalValues)
Вы можете сказать, что Baz
«Переопределение» foo.IsValueLegal
Участник, все остальные типы используют функцию «базы».