#inheritance #interface #f#
Вопрос:
В C# я использую следующую функцию, которую я хочу переместить в F#:
public virtual void BringToTop(LayersEnum _TopMostLayer)
{
if (LayerName == _TopMostLayer)
{
ZIndex = 10;
Visibility = Visibility.Visible;
}
else
{
ZIndex = DefaultZIndex;
Visibility = Visibility.Hidden;
}
}
Предполагая, что у меня есть следующие определения F#, как это реализовано в F#:
type DocumentRadioButtons = ChartLayer | WritingLayer | ImageLayer | TranscriptionLayer | PublisherLayer
module WritingLayer=
type Model =
{ Name: string
Visibility: bool
DefaultZIndex: int
ZIndex: int
}
interface ILayer with
member this.Name with get() = this.Name
member this.Visibility with get() = this.Visibility
member this.DefaultZIndex with get() = this.DefaultZIndex
member this.ZIndex with get() = this.ZIndex
type ProgressNoteWin = {
ConfirmState: ConfirmState option
Encounter: view_doctor_encounter
LastName: string
DocumentLayer: DocumentRadioButtons
WritingLayer: WritingLayer.Model
ImageLayer: ImageLayer.Model
ChartLayer: ChartLayer.Model
}
Моя очень НЕУДАЧНАЯ попытка-это:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then {layer with Visibility =true} else {layer with Visibility = false }
{ m with WritingLayer = BringToTop documentRadioButton m.WritingLayer},
Ошибка: Метка записи «Видимость» не определена
Спасибо вам за любую помощь.
#Добавление:
В конечном счете, я хотел бы реализовать интерфейс для различных типов записей WritingLayer.Модель, слой изображений.Модель и составитель карт.Модель, которая будет использоваться в качестве:
{m with WritingLayer = BringToTop rb m.WritingLayer;
ImageLayer = BringToTop rb m.ImageLayer;
ChartLayer = rb m.ChartLayer}
Спасибо вам за ваше внимание.
Комментарии:
1. Сообщение об ошибке означает , что вы, вероятно, забыли
open WritingLayer
это сделать, поэтому тип записи и ее поля не видны в вашей области видимости.2. @FyodorSoikin Проблема здесь в том, что мне также понадобится «Модель» слоя диаграмм и слоя изображений. Спасибо.
3. Подождите, так вы просто спрашиваете, как ссылаться на поля записи, не открывая модуль, в котором определена запись?
Ответ №1:
Этот код не будет работать как есть:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
{ layer with Visibility =true }
else
{ layer with Visibility = false }
Это связано с тем, что F# неявно опускается до типа, реализующего интерфейс.
Первое потенциальное решение:
Переключитесь с передачи an ILayer
на прямую передачу a Model
. Тогда ваш код будет работать.
Второе потенциальное решение:
Я предполагаю, что, поскольку у вас есть интерфейс, вы хотите передать его как тип данных, а не как сам тип модели. Если это так, то я бы рекомендовал использовать объектное выражение для обновления данных следующим образом:
let mkILayer visible (layer: ILayer) =
{ new ILayer with
member this.Name = layer.Name
member this.Visibility = visible
member this.DefaultZIndex = layer.DefaultZIndex
member this.ZIndex = layer.ZIndex }
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
mkILayer true layer
else
mkILayer false layer
Третье потенциальное решение
Если вас устраивает понижение, вы можете затенить свое первое layer
определение следующим образом:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
let layer = layer :?> Model
{ layer with Visibility =true }
else
let layer = layer :?> Model
{ layer with Visibility = false }
Но обычно всякий раз, когда происходит подавление, это запах кода, поэтому я бы действительно рекомендовал вместо этого создать новый экземпляр интерфейса.
Комментарии:
1. Если я сделаю: пусть BringToTop rb (слой:модель) = как в первом потенциальном решении, я получу сообщение об ошибке «Модель не определена». (Это была моя первая попытка). 🙁
2. Второе потенциальное решение возвращает тип ILayer. Мне нужно, чтобы он вернул тип модели, с которого он начинался. То есть, в идеале, BringToTop будет использоваться как: BringToTop rb m.Слой записи, возвращающий слой записи; Слой изображений BringToTop rb с возвратом слоя изображений; слой диаграмм BringToTop rb с возвратом слоя диаграмм. Мы очень ценим вашу помощь. Спасибо.
3. Пожалуйста, смотрите добавление к первоначальному вопросу. Спасибо.
Ответ №2:
Я никогда не мог сделать это так, как хотел-используя интерфейс ILayer для обновления и возврата типа записи, с которым он был связан. Меня больше всего интересовал бы лучший способ сделать это.
В итоге я просто определил три конкретные функции, по одной для каждого типа, как:
let BringToTopWritingLayer rb layer:WritingLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopImageLayer rb layer:ImageLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopChartLayer rb layer:ChartLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
с использованием в качестве:
{ m with DocumentLayer = documentRadioButton;
WritingLayer = BringToTopWritingLayer documentRadioButton m.WritingLayer;
ImageLayer = BringToTopImageLayer documentRadioButton m.ImageLayer;
ChartLayer = BringToTopChartLayer documentRadioButton m.ChartLayer}
Это кажется крайне избыточным, но, похоже, оно компилируется правильно.
Лучший ответ был бы весьма признателен.