Dart – initializing final class members depedent on each other

Issue

I like to use final members in my classes whenever it makes sense, but I ran into a problem trying to do something relatively simple:

import 'dart:ui';

class Foo {
  final PictureRecorder recorder;
  final Canvas canvas;
  final int margin;

  Foo({
    this.margin = 10,
  })  : recorder = PictureRecorder(),
        canvas = Canvas(recorder) { // this line errors out
  }
}

The error I’m getting from the compiler is:

The instance member 'recorder' can't be accessed in an initializer. Try replacing the reference to the instance member with a different expression

Is there another way of doing what I want without making the canvas field non-final?

I know I can make the class look similar "from the outside" using a non-final private field and a custom getter, but it feels like an unnecessary workaround.

Solution

You can make use of a factory constructor which calls your real (hidden) constructor like this:

class Foo {
  final PictureRecorder recorder;
  final Canvas canvas;
  final int margin;

  factory Foo({
    int margin = 10,
  }) {
    final recorder = PictureRecorder();
    final canvas = Canvas(recorder);

    return Foo._(
      recorder: recorder,
      canvas: canvas,
      margin: margin,
    );
  }

  Foo._({
    required this.recorder,
    required this.canvas,
    required this.margin,
  });
}

Since we have yet to create any object when running inside the factory body, we are allowed to do anything as long as we return an object compatible with the type which the factory constructor is part of.

So we can create all necessary values and then forward them to our real constructor and prevent the use of any late variables.

Answered By – julemand101

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *