Skip to content

avoid_accessing_other_classes_private_members

v1.0.0WarningConfigurableCode Quality

This rule flags one class reading another class’s private member.

Dart scopes privacy to the library, not the class. _field is visible to every declaration in the same file — and to every part of it. Most people write _ meaning “mine”, and the language quietly means “this file’s”. In a long file, or a part-heavy library, a class ends up depending on another’s internals with nothing in the code to mark it.

This rule is in the pedantic preset and works with its defaults.

See also: Dart: libraries and privacy

Both classes live in one file, so this compiles. Nothing marks that Report now breaks whenever Account renames a field:

class Account {
int _balance = 0;
}
class Report {
int total(Account account) => account._balance;
}

Expose what the other class actually needs:

class Account {
int _balance = 0;
int get balance => _balance;
}
class Report {
int total(Account account) => account.balance;
}

Another instance of the same class is fine

Section titled “Another instance of the same class is fine”

other._value inside ==, copyWith or a comparison is the pattern, not a violation — it is the class reaching into itself:

class Money {
const Money(this._cents);
final int _cents;
// Not reported — `other` is a Money too.
bool isMoreThan(Money other) => _cents > other._cents;
@override
bool operator ==(Object other) => other is Money && _cents == other._cents;
@override
int get hashCode => _cents.hashCode;
}

A StatefulWidget and its State are one object the framework split in two, so a read through widget is never reported:

class CounterState extends State<Counter> {
// Not reported.
int get start => widget._initial;
}

The exemption keys on the receiver being spelled widget, which is the convention flutter create and every Flutter template produce. A State that renames it loses the exemption.

copyWith, operator ==, hashCode and toString are exempt by default — they exist precisely to read another instance’s fields. Add your own:

many_lints.yaml
rules:
avoid_accessing_other_classes_private_members:
additional_ignored_members: [merge, mergeWith]
class Settings {
Settings(this._values);
final Map<String, String> _values;
// Not reported with the config above.
Settings merge(Settings other) => Settings({..._values, ...other._values});
}

Use ignored_members instead to replace the default list rather than add to it.

Only reads from inside a class are reported. A top-level function in the same library reaching into a class’s private field is not flagged:

class Account {
int _balance = 0;
}
// Not reported — no enclosing class.
int total(Account account) => account._balance;

this._x and a bare _x are the class’s own business and are never reported.

analysis_options.yaml
many_lints:
rules:
avoid_accessing_other_classes_private_members:
additional_ignored_members: [merge]
Option Type Default Description
ignored_members list of strings [copyWith, ==, hashCode, toString] Members whose job is to read another instance’s fields
additional_ignored_members list of strings [] Names to add to that list

To disable this rule:

many_lints.yaml
rules:
avoid_accessing_other_classes_private_members: false

To keep the rule on but skip certain paths, use per-rule exclude.