Home > Net >  How to prevent getter or function from recalculate every time?
How to prevent getter or function from recalculate every time?

Time:11-20

Let say I have class like this

class OrderInfo {
  final String orderId;
  final String status;
  final DateTime orderDateTime;
  final DateTime? deliverDateTime;
  final String? restaurantTitle;

  OrderInfo({
    required this.orderId,
    required this.status,
    required this.orderDateTime,
    required this.deliverDateTime,
    required this.restaurantTitle,
  });
  
  // and a getter
  Something get something {
    // Very long code that I don't want to recalculate
    return something;
  };
}

Since all fields is final, so there's no point to recalculate (return value will be the same).

I tried create field like this.

late Something something = () {
  // Very long code that I don't want to recalculate
  return something;
}();

But I'm not sure this is correct way to do. Is there other method or this is fine?

CodePudding user response:

The late field is fine. I'd make it final, unless you want to allow overwriting the value.

I'd probably extract the computation function into a named helper function, like:

class OrderInfo {
  late final Something something = _computeSomething();
  ...
  Something _computeSomething() {
    // Very long code that I don't want to recalculate
    return something;
  }
}

Keeping the computation on the side makes the variable declaration more readable, and it allows you to reuse _computeSomething if you want to, but otherwise the effect is the same.

If the Something cannot be null, you can also implement your own late variable:

class OrderInfo {
  Something? _something;
  ...
  Something get something => _something ??= _computeSomething();
  ...
}

The only advantage over a late final .. = ... is that it allows you to check whether the _something has been computed or not.

In some cases that's useful. Say the computation allocates a resource, and you want to release that resource later. If you just use a late variable to store the allocated value, all you can do is read that variable or not. Reading it will allocate the resource, if it wasn't already, and then you have to release it. Using a nullable variable, you can check whether there is something to release, and do nothing if not.

In general, if you ever need to know whether a late variable has been initialized, consider not using late to begin with, because late hides the "is initialized" bit from you. Hiding details is what makes the late final something = ...; so nice and short, so using late final is fine when you don't need to know.

(I'd generally recommend against exposing late public fields that are not final, or that do not have an initializing expression, because that will also expose a setter for the field. It either exposes the potentially uninitialize field to your users, risking it throwing when read, or it exposes a setter in your API that users cannot call anyway. A late final variable with an initializer expression is great, because it doesn't have a setter, and it is always initialized when it's read.)

CodePudding user response:

save result into a final variable, then the getter only take the result, it will not recalculate :

class OrderInfo {
  final String orderId;
  final String status;
  final DateTime orderDateTime;
  final DateTime? deliverDateTime;
  final String? restaurantTitle;

  late final Something _somethingFinal;

  OrderInfo({
    required this.orderId,
    required this.status,
    required this.orderDateTime,
    required this.deliverDateTime,
    required this.restaurantTitle,
  }){
    _somethingFinal = _calculateSomthing();
  }

  // and a getter
  Something get something {
    // Very long code that I don't want to recalculate
    return _somethingFinal;
  }

  Something _calculateSomthing(){
    return Something();
  }

}

class Something{
}
  •  Tags:  
  • dart
  • Related