Dart - Using Access Modifiers (Private & Public)

This tutorial shows you how to define access modifer for data members in a Dart class.

In Java, we can use public, protected, and private keywords to control the access scope for a property or method. However, Dart doesn't provide that kind of keywords. Instead, you can use _ (underscore) at the start of the name to make a data member of a class becomes private.

In Dart, the privacy is at library level rather than class level. It means other classes and functions in the same library still have the access. So, a data member is either public (if not preceded by _) or private (if preceded by _)

Usage on Fields

For example, there is a library a.dart with a class named A. The class has two fields: first (public) and _second (private).

a.dart

  class A {
    String first;
    String _second;
  }
  
  void main() {
    A a = new A();
    a.first = 'New first';
    a._second = 'New second';
    print('${a.first}: ${a._second}');
  }

It works fine when _second is accessed within the same library, even from a function (main) outside the class. What will happen if it's accessed outside the library? Take a look at the example below.

other.dart

  import 'a.dart';
  
  void main() {
    A a = new A();
    a.first = 'New first';
    a._second = 'New second'; // The setter _second is not defined for the class 'A'
    print('${a.first}: ${a._second}'); // The getter _second is not defined for the class 'A'
  }

If you try to run the code, you will get compile error that the setter or getter is not defined for the class. You should have got warned if you are using IDE. If you need to access _second outside a.dart, you have to create a getter and setter for it which must be non-private.

a.dart

  class A {
    String first;
    String _second;
  
    String get second {
      return _second;
    }
  
    void set second(String second) {
      this._second = second;
    }
  }

In the other file, instead of accessing the field directly, use the getter and setter.

other.dart

  import 'a.dart';
  
  void main() {
    A a = new A();
    a.first = 'New first';
    a.second = 'New second';
    print('${a.first}: ${a.second}');
  }

Usage on Functions

The same thing also applies on class function (which is usually referred to as method). A function with _ modifier can only be accessed within the library.

a.dart

  class A {
    // Fields
    // Getters and setters
  
    void _printFields() {
      print('First: $first, second: $_second');
    }
  }

If you call that function outside the library.

other.dart

  import 'a.dart';
  
  void main() {
    A a = new A();
    a.first = 'New first';
    a.second = 'New second';
    a._printFields(); // The getter _printFields is not defined for the class 'A'
  }

You'll get the similar error when compiling the code. Removing the _ modifier, makes it becomes public which means you can access the function outside the library.

a.dart

   class A {
  	// Fields
  	// Getters and setters
  
    void printFields() {
      print('First: $first, second: $_second');
    }
  }

other.dart

  import 'a.dart';
  
  void main() {
    A a = new A();
    a.first = 'New first';
    a.second = 'New second';
    a.printFields();
  }

Inheritance

The same rule also appllies for inheritance. For example, we have a class B which is the sub-class of A.

  class B extends A {
    printA() {
      _printFields();
    }
  }

B can only access private fields and attributes of A only if it's placed in the same library. Moving the code above outside the library, it will cause error with reason the method is not defined for class B.

Tips: Don't use _ on local variable

The private concept is not for local variable. Therefore, avoid using _ for local variables.