Multiple constructors and class inheritance in F #

I find it difficult to convert the following C # code to F #:

class Foo { public Foo() { } public Foo(string name) { } } class Bar : Foo { public Bar() : base() { } public Bar(string name) : base(name) { } public string Name { get; set; } } 

I tried the following first, but it reports an error

Constructors for the Bar type must directly or indirectly call it the implicit object constructor. Use an implicit object call instead of a record expression.

 type Foo() = new(name:string) = Foo() type Bar() = inherit Foo() new(name:string) = { inherit Foo(name) } member val Name:string = null with get, set 

Then I tried the following, but now it reports an error in the auto property

Val member definitions are allowed only on types with a primary constructor. Consider adding arguments to the type definition.

 type Foo() = new(name:string) = Foo() type Bar = inherit Foo new(name:string) = { inherit Foo(name) } member val Name:string = null with get, set 
+5
source share
3 answers

If you want the source code F #, which compiles the exact same API as your C # code, looks like this:

 type Foo = new() = {} new(name:string) = { } type Bar = inherit Foo [<DefaultValue>] val mutable private name:string new() = { inherit Foo() } new(name) = { inherit Foo(name) } member x.Name with get() = x.name and set v = x.name <- v 
+5
source

This compiles:

 type Foo() = new(name:string) = Foo() type Bar(name : string) = inherit Foo() new() = Bar(null) // or whatever you want as a default. member val Name:string = name with get, set 

See Constructors (F #) and Inheritance (F #) .

Looking at decompilation, C # will (with attributes removed):

 public class Bar : Program.Foo { internal string Name@ ; public string Name { get { return this.Name@ ; } set { this.Name@ = value; } } public Bar(string name) { this.Name@ = name; } public Bar() : this(null) { } } public class Foo { public Foo() { } public Foo(string name) : this() { } } 
+1
source

If a class has a list of parameters immediately after its name (including () ), it has a primary constructor. Using it, any inherit are placed only in this primary constructor, which comes immediately after the class declaration and before any member declarations.

It is not clear what you are trying to achieve. The Foo class has a constructor that takes a string argument, only to remove it. A (technically) valid similar pair of classes would be this:

 type Foo(name:string) = member f.NameLength = name.Length type Bar(initialName) = // WARNING: this will not end well inherit Foo(initialName) member val Name:string = initialName with get, set 

But this is not reasonable code. Foo will keep the initial name, even if the name in Bar is changed. Bar.Name.Length returns the current length of the name, and Bar.NameLength returns the initial length of the name.

To keep the default constructor, you can add new () = Bar(null) (or the equivalent in Foo ), but note that null is considered a function for interaction only . It is not used in F # code; if possible, use the appropriate parameter type or empty string, respectively (depending on whether the string is empty or does not exist at all).

In addition, class inheritance is not recommended in F # component design directives - for good reason. There are few use cases, but usually they include a tiny base class and a derived class, which is a great addition to it. More often, types have to be constructed using one class as a member of another.


I don’t know how relevant this is, but here is an example of a class with a standard constructor and an additional constructor that uses it:

 type Text500(text : string) = do if text.Length > 500 then invalidArg "text" "Text of this type cannot have a length above 500." member t.Text = text new () = Text500("") 

This uses the primary constructor to validate input and has an optional parameterless constructor that uses an empty string. (I'm not sure if the extra constructor will be useful in real applications.)

+1
source

Source: https://habr.com/ru/post/1208037/


All Articles