prefer-constructors-over-static-methods

Same as prefer_constructors_over_static_methods in Dart lints

Group
Style
Path
lint/style/prefer-constructors-over-static-methods
Default
Off, opt in
Origin
Dart lints
Rule
332 of 512

Flags static methods that create and return an instance of their own class.

A static method whose job is to build an instance of the enclosing type is a named constructor in disguise. Named (and factory) constructors make the intent explicit, show up as constructors in tooling, and work with constructor tear-offs.

class Point {
  final num x, y;
  Point(this.x, this.y);
  static Point polar(num theta, num radius) =>   // flagged
      Point(radius * cos(theta), radius * sin(theta));
  Point.fromPolar(num theta, num radius)         // preferred
      : x = radius * cos(theta), y = radius * sin(theta);
}

Only non-generic static methods and getters of non-generic classes and extension types are checked. As in the analyzer, the last visited constructor call determines whether the body creates the declared enclosing return type.

Invalid

example.dartdart
class Point {
  final num x;
  final num y;
  Point(this.x, this.y);

  static Point polar(num theta, num radius) =>
      Point(radius * theta, radius * theta);

  static Point origin() {
    return Point(0, 0);
  }

  static Point fromList(List<num> xs) {
    final p = Point(xs[0], xs[1]);
    return p;
  }
}

class Named {
  final String name;
  Named._(this.name);

  static Named create(String name) => Named._(name.trim());
}

class WithNew {
  WithNew();

  static WithNew make() => new WithNew();
}

class Implicit {
  static Implicit build() => Implicit();
}

class Singleton {
  static Singleton get instance => Singleton();
}

class NamedCreation {
  const NamedCreation.fallback();
  static NamedCreation of(Object? value) => value as NamedCreation? ?? const NamedCreation.fallback();
}

class PrunedArguments {
  PrunedArguments(Object value);
  static PrunedArguments create() => PrunedArguments(Object());
}

class ClosureCreation {
  static ClosureCreation create() {
    final make = () => ClosureCreation();
    return make();
  }
}
Static method should be a constructor.
5
6 static Point polar(num theta, num radius) =>
Static method should be a constructor.
8
9 static Point origin() {
Static method should be a constructor.
12
13 static Point fromList(List<num> xs) {
Static method should be a constructor.
22
23 static Named create(String name) => Named._(name.trim());
Static method should be a constructor.
28
29 static WithNew make() => new WithNew();
Static method should be a constructor.
32class Implicit {
33 static Implicit build() => Implicit();
Static method should be a constructor.
36class Singleton {
37 static Singleton get instance => Singleton();
Static method should be a constructor.
41 const NamedCreation.fallback();
42 static NamedCreation of(Object? value) => value as NamedCreation? ?? const NamedCreation.fallback();
Static method should be a constructor.
46 PrunedArguments(Object value);
47 static PrunedArguments create() => PrunedArguments(Object());
Static method should be a constructor.
50class ClosureCreation {
51 static ClosureCreation create() {

Valid

example.dartdart
class Point {
  final num x;
  final num y;
  Point(this.x, this.y);

  Point.polar(num theta, num radius)
      : x = radius * theta,
        y = radius * theta;

  // Nullable return type: a constructor cannot return null.
  static Point? tryParse(String text) => text.isEmpty ? null : Point(0, 0);

  // Generic static method.
  static Point first<T>(List<T> xs) => Point(xs.length, 0);

  // Returns a cached instance without constructing one.
  static final Point _zero = Point(0, 0);
  static Point zero() => _zero;

  // Instance method creating a new instance.
  Point translate(num dx) => Point(x + dx, y);

  // Returns another type.
  static String describe() => Point(0, 0).toString();
}

// Generic classes are skipped.
class Box<T> {
  final T value;
  Box(this.value);
  static Box<int> ofInt() => Box<int>(0);
}

// Factory constructor already.
class Logger {
  Logger._();
  factory Logger.create() => Logger._();
}

// Returning a subtype instance.
class Shape {
  static Shape square() => Square();
}

class Square extends Shape {}

// The analyzer's visitor overwrites earlier matching constructor calls.
class LastCreation {
  static LastCreation create() {
    final value = LastCreation();
    Object();
    return value;
  }
}

class DefaultParameterOnly {
  const DefaultParameterOnly();
  static DefaultParameterOnly create([
    DefaultParameterOnly value = const DefaultParameterOnly(),
  ]) => value;
}

class ClosureOverwrite {
  static ClosureOverwrite create() {
    final value = ClosureOverwrite();
    final other = () => Object();
    return value;
  }
}

Configure prefer-constructors-over-static-methods

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-constructors-over-static-methods": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/prefer-constructors-over-static-methods: <reason>