Search code examples
dartpass-by-referencepass-by-value

Why Dart is acting as pass by reference?


I know that dart is passing by value just like Java, but I don't understand why in the following example it acts like passing by reference?

class A {
  int y = 10;
}

class B {
  List<A> list = [];
  void add(A a) {
    a.y = 20;
    list.add(a);
  }

  void runtest() {
    print(list[0].y);
  }
}

void main() {
  A a = A();
  B b = B();
  b.add(a);
  print(a.y);
  b.runtest();
}

The result will be

20
20

why when the variable (y) for the object (a) was changed inside the method (add) inside (b), it also changed the variable (y) of the object (a) inside main()?


Solution

  • I think your confusion comes from a misunderstanding about what variables and parameters are and the concept of pass by reference and pass by value.

    A variable in Dart can be seen as a reference to a object. When you give this variable as a parameter to a method you are essential given a copy of this reference. The method can therefore not change what object this reference are pointing to. But the method do have access to the object itself since it got a copy of the reference. We are therefore not creating copies of objects when we give a variable to a method.

    Some objects in Dart are immutable (like String, int, double etc.) so a method will not be able to change the inner state of these types of objects. So even if we got a copy of a reference to some of these objects, we cannot change the state and therefore we seen this like "pass by value" behavior.

    But if an object (e.g. List) are able to change its inner state, we can make modification like adding items to a List object. Since we never create new objects we will see this change outside our method since we have made a change to the object itself without any change to the reference. This gives this "pass by reference" behavior you see in your example.

    But this does not change the fact that the variable itself are a reference which always "pass by value" when given to methods as parameter.

    A small example showing what I mean by "pass by value" when we talk about parameter to methods, can be seen here:

    class A {
      int value;
    
      A(this.value);
    }
    
    void main() {
      final a = A(1);
      print(a.value); // 1
      myMethod(a);
      print(a.value); // 1
    }
    
    void myMethod(A a) {
      a = A(2);
    }
    

    As the example shows, the a variable in myMethod can be changed to point to another object but since this variable is pass by value, the change will not happen in main.