Search code examples
flutterdartpass-by-referencepass-by-value

Pass by value makes me lose last value of variable


I have two global scope variables, one stores a list of cars and the other creates an instance of Car

Car car = Car('', '');
List<Car> cars = [];

On each screen of my forms I assign some information to a parameter of my car instance and at the end of the registration I assign the car instance to a private scope variable and add it to my list of cars that will be displayed on the initial screen

car.fuelPrice = '2,50';

[...]

Car _newCar = Car('', '');
_newCar = car;
cars.add(_newCar);

My problem is that I need to register new cars based on the car already registered and for that I need to modify the value of some parameters (I delete the value supplied, for example) and consequently the list item of my variable cars is also modified, because its value pointed to the object I changed. This means that when I return to the car listing screen, I have lost the value of the first registered car and display two cars listed, containing the same information, the information that I registered last time

print(cars); // [Car(1, 'Ford', '2,50')]

car.id = null;
car.brand = 'Chevrolet';
car.model = '1,45';

print(cars);  // [Car('Chevrolet', '1,45'), Car('Chevrolet', '1,45')]

I read articles that say that there is only passing by value in Dart, however they also say that this value is a reference to the object stored in memory (What is the true meaning of pass-by-reference in modern languages like Dart?) and that gives me a problem.

I would like to keep this approach of using a global scope list, so that whenever I return to the screen where I list the cars I don't need to query the local database to bring this information, I will already have the information and, if possible, I would like the car instance to also remain globally scoped so I don't have to pass it in the constructor of each of my forms

What I've already tried and it didn't work:

I've already tried passing the Car object to Map and I've tried creating a method that returned a list of private scope cars and assigning it to the global list

How can I resolve this issue without having to change all forms by passing car as a private scope?


Solution

  • the other creates an instance of Car

    No, a variable is a reference to an object; it doesn't itself create an instance. Invoking the Car constructor creates the instance, and your global variable stores a reference to that instance.

    If you want something that creates an instance, then you therefore ultimately need to call a constructor for each instance. If you want to use an existing instance as a template for a new instance, a common pattern in Dart is to provide a copyWith method that invokes a constructor appropriately:

    class Car {
      String brand;
      String model;
    
      Car(this.brand, this.model);
    
      Car copyWith({String? brand, String? model}) {
        return Car(
          brand ?? this.brand,
          model ?? this.model,
        );
      }
    }
    

    Note that the above approach needs to be adjusted if your class has nullable properties.