Interfaces and abstract classes in F #

I am trying to create a small piece of code in F #. The idea is that I will have an interface that defines several methods, properties, and events. Using this interface, I want to define an abstract class (having a common type) that will implement some properties / methods, but not all members defined in the interface. Responsibility for defining all members will be for derived classes.

So far, I have stuck with the interface and the abstract class. The problems that I have are:

  • An abstract class definition does not recognize an interface definition
  • I'm not sure how to define abstract elements for an interface in an abstract class

The interface compiles fine, but the abstract class has several errors. Messages are included in the code.

All comments, corrections, tips, etc. appreciated. Since this is my first F # test, there are probably a lot of errors to point out.

Code i still

Interface Definition

namespace A type IValueItem = interface [<CLIEvent>] abstract member PropertyChanged : Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, System.ComponentModel.PropertyChangedEventArgs> abstract ConvertedX : double with get, set abstract Y : double with get, set abstract member CreateCopy : obj abstract member NewTrendItem : obj end 

And an abstract class

 namespace A [<AbstractClass>] type ValueItem<'TX>() = [<DefaultValue>] val mutable _y : double let _propertyChanged = new Event<_>() // ERROR: This type is not an interface type // ERROR: The type 'obj' is not an interface type // ERROR: The type 'IValueItem' is not defined interface IValueItem with // ERRROR No abstract or interface member was found that corresponds to this override [<CLIEvent>] member this.PropertyChanged : Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, System.ComponentModel.PropertyChangedEventArgs> = _propertyChanged.Publish // This definition is incomplete, should be abstract member ConvertedX : double with get, set // ERROR: Incomplete structured construct at or before this point in pattern member CreateCopy() : obj member NewTrendItem() : obj abstract X : 'TX with get, set member this.Y with get() = this._y and set(value) = if this._y <> value then this._y <- value this.NotifyPropertyChanged("Y") member this.NotifyPropertyChanged(propertyName) = this.PropertyChanged.Trigger(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)) 
+5
source share
1 answer

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)

+7
source

All Articles