5

Let's take this class:

type Test() =

    let mutable Flag1 : bool = false
    [<DefaultValue>] val mutable Flag2 : bool

    do
        Flag1 <- true  // that works
        Flag2 <- true  // nope... why?

    member this.SetFlag =
        Flag1 <- true  // no 'this' instance? does that mean it's static?
        this.Flag2 <- true  // that works now, but still no way to set a default value

Why do I need [<DefaultValue>] when I want to be able to set the value to whatever myself?

and then now:

type Test2() =
    Inherit(Test)

    do
        Flag1 <- true  // not accessible
        Flag2 <- true  // not happening either

    member this.SetFlag2 =
        Flag1 <- true  // not accessible
        this.Flag2 <- true  // ok

so I could do:

    member val Flag1 : bool with get, set

but why isn't the syntax val this.Flag1 since it's part of the instance? and.. I can't access that from the constructor.

Can anyone explain how this works? because it's very confusing. It looks like the usefulness of constructors is quite low if you can't set things in there. Or, am I missing something? And I can't construct an instance of the class and set variables though a new() constructor since the last statement needs to return the instance, so I can't create an instance, set everything I need and then return it. Or, is it possible?

Also, how can I have a field that:

  • Is an instance field, not static
  • I can initialize to whatever I want in the constructor
  • Is mutable
  • Is accessible from member functions

like a plain field in C# in essence.

What I am trying to implement is: I need to have a timer object that belongs to the class instance and can be initialized in the constructor. Class methods need to have access to the timer and the timer's callback needs to have access to class fields.

In pseudo C#, I'd have something like this:

Class A
{
    public Timer MyTimer;
    public bool Flag1, Flag2;

    A()
    {
        MyTimer = new Timer(Callback);
    }

    public void StartTimer()
    {
        MyTimer.Start();
    }

    public void Callback()
    {
        if (Flag1) Flag2 = true;
    }
}

public class B : A
{
    public void DoStuff()
    {
        Flag1 = True;
    }
}
Thomas
  • 10,933
  • 14
  • 65
  • 136
  • There's a related question https://stackoverflow.com/questions/41394921/f-object-initialization-with-a-constructor about constructor initialization. – karmakaze Dec 28 '19 at 02:48

1 Answers1

0

What you need is to specify a type instance alias for all it's body:

type Test() (*here is the part you need: *) as this = 
    // ...
    // and then you can access your public mutable field by type instance alias:
    do this.Flag2 <- true

Also, in your second inherited class (Test2), you can access the Flag2 field with the same syntax. And, by the way Field1 can't be accessed in Test2 class because it's private because you have defined it using let binding

Viacheslav
  • 120
  • 2
  • 11