How to Implement Singleton Pattern without Nullable

474 views Asked by At

I am trying to implement the Singleton pattern in Hack. However, I keep running into issues with Nullable.

<?hh //strict

class Foo {
    private static Foo $foo;

    public function __construct() {
        // Do stuff here.
    }        

    public static function theFoo(): Foo {
        if (null === self::$foo) {
            self::$foo = new Foo();
        }

        return self::$foo;
    }
}

$aFoo = Foo::theFoo();

When executed I get the error:

Catchable fatal error: Hack type error: Please assign a value at foo.hh line 4

The type checker returns a similar as well:

foo.hh:4:24,27: Please assign a value (Typing[4055])

How do I assign a default value to a static property?

1

There are 1 answers

4
Josh Watzman On BEST ANSWER

How do I assign a default value to a static property?

If it's an object, like in this case, you can't. With primitives, you can do something like this:

<?hh // strict

class Foo {
  private static int $x = 0;
  // ...
}

However, for objects, you'd need to say private static Foo $x = new Foo() which isn't allowed -- you can't initialize static variables like that, since it has to call the constructor, which involves running code, and PHP doesn't have a notion of initialization order and running code like this (which other languages, notably C++, do). There's no deep technical reason we couldn't have such a notion, it's just not part of the language right now.

The right thing to do is just make the static nullable. You're actually already implicitly treating it as such, when you do the if (null === self::$foo) -- as written, self::$foo actually can't be null since you haven't given it a nullable type, and so that check does nothing. What you probably mean to do is this:

<?hh // strict

class Foo {
  private static ?Foo $foo;
  // ...
}