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

[patterns] Object pattern with redirecting factory constructors #3159

Closed
dnys1 opened this issue Jun 22, 2023 · 4 comments
Closed

[patterns] Object pattern with redirecting factory constructors #3159

dnys1 opened this issue Jun 22, 2023 · 4 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@dnys1
Copy link

dnys1 commented Jun 22, 2023

I searched the issues and couldn't find a related discussion, but apologies if I missed it. I'm wondering if there has been consideration for allowing factories in destructure/object patterns?

A motivating example for this is the following sealed class hiearchy:

// shape.dart
import 'dart:math';

sealed class Shape {
  const Shape();

  const factory Shape.circle(double radius) = _Circle;
  const factory Shape.square(double side) = _Square;
}

final class _Circle extends Shape {
  const _Circle(this.radius);

  final double radius;
}

final class _Square extends Shape {
  const _Square(this.side);

  final double side;
}

// main.dart
void main() {
  final Shape shape = Shape.circle(2.0);
  final area = switch (shape) {
    Shape.circle(:final radius) => radius * radius * pi,
    Shape.square(:final side) => side * side,
  };
}

While it's certainly possible to just make Circle and Square public, the beauty of redirecting factories IME is that it improves the discoverability of subclasses in ADTs, where the enumeration of all values is visible on the base class. It would be great if, in the same way these classes are constructed, they could likewise be destructured which would reduce confusion and developer cycles.

@dnys1 dnys1 added the feature Proposed language feature that solves one or more problems label Jun 22, 2023
@rrousselGit
Copy link

Wouldn't that cause public properties in private classes to leak?

Technically _Circle.radius is not accessible from outside the library defining _Circle.

@dnys1
Copy link
Author

dnys1 commented Jun 22, 2023

Hmm.. if that is a sticking point, then the example and rationale hold for when Circle and Square are instead public.

@munificent
Copy link
Member

In general, I don't think factory constructors would work well with pattern matching. The problem is that from the declarations, all we know is that Shape.circle and Shape.square both return Shape. The exhaustiveness checker doesn't know that the former returns _Circle and the latter _Square. In the absence of that, it doesn't know those cases are exhaustive.

In theory, it could know this because these happen to be const constructors and it could the examine the body of the constructor. But that feels pretty brittle to me.

I think you're better off just making the two subclasses public and let the user construct them directly. If we ever do #336, then you could nest the declarations of Circle and Square directly inside Shape, which would give you the discoverability you want and work well with pattern matching.

@munificent munificent closed this as not planned Won't fix, can't repro, duplicate, stale Aug 15, 2023
@dnys1
Copy link
Author

dnys1 commented Aug 15, 2023

Thanks @munificent! I agree #336 seems like a better solution overall.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants