Avoid overriding a final field to return different values if called multiple times.

This rule is currently experimental and not yet available in a stable SDK.


AVOID overriding or implementing a final field as a getter which could return different values if it is invoked multiple times on the same receiver. This could occur because the getter is an implicitly induced getter of a non-final field, or it could be an explicitly declared getter with a body that isn’t known to return the same value each time it is called.

The underlying motivation for this rule is that if it is followed then a final field is an immutable property of an object. This is important for correctness because it is then safe to assume that the value does not change during the execution of an algorithm. In contrast, it may be necessary to re-check any other getter repeatedly if it is not known to have this property. Similarly, it is safe to cache the immutable property in a local variable and promote it, but for any other property it is necessary to check repeatedly that the underlying property hasn’t changed since it was promoted.


class A {
  final int i;

var j = 0;

class B1 extends A {
  int get i => ++j + super.i; // LINT.

class B2 implements A {
  int i; // LINT.


class C {
  final int i;

class D1 implements C {
  late final int i = someExpression; // OK.

class D2 extends C {
  int get i => super.i + 1; // OK.

class D3 implements C {
  final int i; // OK.


To enable the avoid_unstable_final_fields rule, add avoid_unstable_final_fields under linter > rules in your analysis_options.yaml file:

    - avoid_unstable_final_fields