Description
Consider the following example:
/// lib1.dart
class Addable {
final int _value;
Addable(this._value);
operator +(Addable addable) {
return Addable(_value + addable._value);
}
}
/// lib2.dart
import 'lib1.dart';
class DecoratedAddable implements Addable {
final Addable _decorated;
DecoratedAddable(this._decorated);
@override
operator +(Addable addable) {
print('Adding');
return _decorated + addable;
}
}
/// main.dart
import 'lib1.dart';
import 'lib2.dart';
void main() {
Addable(1) + DecoratedAddable(Addable(2));
}
Running dart run main.dart
issues the expected error:
Unhandled exception:
NoSuchMethodError: Class 'DecoratedAddable' has no instance getter '_value'.
Receiver: Instance of 'DecoratedAddable'
Tried calling: _value
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
dart-lang/sdk#57147 DecoratedAddable._value (lib1.dart:2:13)
dart-lang/sdk#57148 Addable.+ (lib1.dart:7:37)
dart-lang/sdk#57149 main (main.dart:5:14)
dart-lang/sdk#57150 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
dart-lang/sdk#57151 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
My desire is if the analyzer could warn whenever you are using a private member of a different instance of a class which can be implemented by a foreign library. In this case, if a warning could be issue in Addable
when performing: Addable(_value + addable._value);
that addable._value
is unsafe since the passed in Addable
may be a different implementation.
Of course if Addable
was private this shouldn't warn since we can be certain all the fields will be implemented.
This issue has been on my mind for quite some time since it requires you to be constantly focused on what you're doing with your classes.
To illustrate this point further. Here is at least one example of this issue in the sdk, in the Duration
class:
sdk/sdk/lib/core/duration.dart
Lines 193 to 201 in edb7fb4
and some more unsafe usages at other operators:
sdk/sdk/lib/core/duration.dart
Lines 223 to 233 in edb7fb4
While the fix is trivial here, as is, if a client wanted to, for some reason, decorate the Duration
class, and through implements
rather than extend
, these methods would fail.
Another way to safe-guard against this issue, would be either that no public class that defines a private field / method can be implemented by a different library only extended. I assume this would require some specification changes.