6

A common Dart pattern before null safety for creating static method holder classes was the following:

class MyMethodScope {
  /// Prevents instantiation of this class.
  factory MyMethodScope._() => null;

  static void noop() {}
}

This is not possible with null safety because the return type of a factory constructor is not nullable apparently.

creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
  • Can you show an example of how do you call the factory method? I haven't tested it with the new null safety but I believe a factory is allowed to return null, maybe where you call it use the new notation MyMethodScope? to let it know it can be null – EdwynZN Jun 23 '20 at 23:26
  • @EdwynZN It is not intended to be called - it is a safety measure basically. It is a compile-time error with the new null safety :) – creativecreatorormaybenot Jun 23 '20 at 23:40
  • Yeah I see now all are null safe unless you explicitly say not to, but a factory constructor has no return type to change it with the ? – EdwynZN Jun 24 '20 at 00:06
  • @EdwynZN Yes, exactly that is what I am wondering about (: – creativecreatorormaybenot Jun 24 '20 at 01:09

1 Answers1

5

Based on https://github.com/dart-lang/language/issues/604, it looks expected that factory constructors can no longer return null, so you can't do it.

You alternatively could just use a private constructor (whether factory or not) that returns a non-null object. That would still prevent the class from being instantiated outside of the library. (Of course, it wouldn't prevent the class from being instantiated within the library, but you could just avoid doing that since you control your own library. You could move the class into a separate library if you're still concerned about accidental instantiation.)

Or just declare the class as abstract, which is the normal and direct way to prevent a class from being instantiated.

Besides, Effective Dart says to avoid such classes.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • I'm running into a problem with singleton classes that have constructor arguments. The compiler doesn't recognize that the non-nullable members are being set in the factory. It will compile if I a) define my members as nullable or b) use the late modifier. Does anyone know if there is a better approach? Path a doesn't show clear intent and path b feels a little awkward. – Nathan Agersea Oct 25 '21 at 17:26
  • 1
    @NathanAgersea Non-nullable members should be initialized by the non-`factory` constructor that the `factory` constructor delegates to. – jamesdlin Oct 25 '21 at 17:28
  • I went down the rabbit hole with this and, from what I've read, singleton is not intended to provide for constructor arguments. So path b) late key word establishing that the class member will be set, and delegating to the factory, follows builder and is correct. Do I have this right? – Nathan Agersea Oct 25 '21 at 18:17
  • @NathanAgersea Singletons often don't make sense with constructor arguments, but they are possible. You just have to define what it means: should supplying a different argument create a new object or return the existing object? If returning the existing object, should it be mutated? See https://stackoverflow.com/a/69669603 for an example. – jamesdlin Oct 25 '21 at 18:36
  • My singleton is essentially config for a package I use to maintain shared code. – Nathan Agersea Nov 01 '21 at 17:17