An abstract class definition does not recognize an interface definition
The interface must be the abstract class declared above : either in the referenced project / assembly in a file above your current file (file order) or higher in the same file.
I'm not sure how to define abstract elements for an interface in an abstract class
Unfortunately, we must implement all the members of the interface in order to preserve the behavior that you want the implementation call to be an abstract element of the class that has the same signature:
type IValueItem = [<CLIEvent>] abstract PropertyChanged : Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, System.ComponentModel.PropertyChangedEventArgs> abstract ConvertedX : double with get, set abstract Y : double with get, set abstract CreateCopy : obj abstract NewTrendItem : obj [<AbstractClass>] type ValueItem<'TX>() = let mutable y = 0.0 let propertyChanged = Event<_, _>() interface IValueItem with [<CLIEvent>] member __.PropertyChanged : Control.IEvent<_, _> = propertyChanged.Publish member this.ConvertedX with get() = this.ConvertedX and set(x) = this.ConvertedX <- x member this.CreateCopy = this.CreateCopy member this.NewTrendItem = this.NewTrendItem member this.Y with get() = this.Y and set(y) = this.Y <- y abstract ConvertedX : double with get, set abstract CreateCopy : obj abstract NewTrendItem : obj member this.Y with get() = y and set(value) = if y <> value then y <- value this.NotifyPropertyChanged("Y") abstract X : 'TX with get, set member this.NotifyPropertyChanged(propertyName) = propertyChanged.Trigger(this, System.ComponentModel.PropertyChangedEventArgs(propertyName))
Property Y defined twice, which at first looks a bit odd. The implementation of the interface is distracted by the implementation in the class - this means that to access Y you do not need to raise an instance of the class to the interface, I did this to maintain the same behavior as your original example
To your comment:
To get a virtual member in an abstract class, you need to declare it as abstract and provide a default implementation, here is an example of code matching in your comment:
type IValueItem = abstract NewTrendItem : unit -> obj [<AbstractClass>] type ValueItem<'TX>() = interface IValueItem with member this.NewTrendItem() = this.NewTrendItem() abstract NewTrendItem : unit -> obj default __.NewTrendItem() = null type NumberItem() = inherit ValueItem<double>() override __.NewTrendItem() = new NumberItem() :> obj
Usually OO F # is used to interact with the rest of the .NET world - it looks like this. But if the code does not interact with another .NET API that requires an OO interface, you may find that modeling a problem with a functional approach can lead to some cleaner code. OO in F # may not give an initial good impression of the language (although I personally really like the explanation and brevity of it)