Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: redirecting_factory #4909

Open
nate-thegrate opened this issue Mar 2, 2024 · 3 comments
Open

proposal: redirecting_factory #4909

nate-thegrate opened this issue Mar 2, 2024 · 3 comments
Labels
lint-proposal status-pending type-enhancement A request for a change that isn't a bug

Comments

@nate-thegrate
Copy link

nate-thegrate commented Mar 2, 2024

redirecting_factory

// before
factory Class.constructor(int a, int b, {String? c, List d = const []}) => Other.constructor(a, b, c: c, d: d);

// after
factory Class.constructor(int a, int b, {String? c, List d}) = Other.constructor;

Redirecting factories can clean things up nicely—you can rely on the other constructor to handle default arguments, and you can even have a const factory if you're redirecting to a const constructor.

Description

Use a redirecting factory constructor instead of a function body.

Details

This rule applies to any factory that simply returns an instance of the class using another constructor with the same parameters.

Kind

This is a "prefer" guideline that would enforce style advice.


Example

class A {
  const A({this.a, this.b, this.c});

  A.fromMap(Map<String, Object?> map)
      : a = map['a'] as double?,
        b = map['b'] as double?,
        c = map['c'] as double?;

  // TODO: add factory constructors

  final double? a, b, c;
}

class B extends A {
  const B(double numerator, double denominator)
    : super(
        a: numerator,
        b: denominator,
        c: numerator / denominator,
      );
}

Bad:

  factory A.fromJson(Map<String, Object?> json) => A.fromMap(json);
  factory A.divide(double numerator, double denominator) {
    return B(numerator, denominator);
  }

Good:

  factory A.fromJson(Map<String, Object?> json) = A.fromMap;

  const factory A.divide(double numerator, double denominator) = B;

Discussion

As mentioned on Stack Overflow, right now there's barely any documentation for factory assignment, so updating the docs should probably happen before the implementation of this lint rule.

@bwilkerson
Copy link
Member

The language specification refers to that as a redirecting factory constructor.

There is a similar structure known as a redirecting generative constructor that can be used for non-factory constructors. If this lint is approved we should consider whether to also catch cases where that construct could be used.

@nate-thegrate nate-thegrate changed the title proposal: assignable_factory proposal: redirecting_factory Mar 4, 2024
@nate-thegrate
Copy link
Author

The language specification refers to that as a redirecting factory constructor.

That's good to know, thanks!

@lrhn
Copy link
Member

lrhn commented Mar 5, 2024

I don't think there'll be any cases for redirecting generative constructors. This only makes sense for an existing factory constructor which uses a body to call another constructor.
Making it a non-factory constructor is a bigger change, and something that should be chosen deliberately.
(There can be a "quick fix" for changing a redirecting factory constructor to a redirecting generative constructor, or vice versa, but neither is better, just different.)

@srawlins srawlins added the type-enhancement A request for a change that isn't a bug label Mar 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lint-proposal status-pending type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants