I have an abstract class that adds strings to a list and does some other stuff.
abstract class Abc {
final _list = <String>[];
Function(String) addedValue;
void add(String s) {
_list.add(s);
if (this.addedValue != null) this.addedValue(s);
}
}
In my subclass I want a callback every time a string is added to the list. There are also other subclasses that may or may not want callbacks.
class Xyz extends Abc {
String _data = '';
Xyz() {
this.addedValue = _added;
}
void _added(String s) {
_data += '$s,';
print('data: $_data');
}
}
main() {
var a = Xyz();
a.add('hello');
a.add('goodbye');
a.addedValue('a'); // Prefer if this was not possible.
a.addedValue = null; // Prefer if this was not possible.
}
What is the cleanest way to provide the superclass with the callback method?
You could make a method like setCallback
in the Abc
abstract class which makes it possible to set the callback but no longer allow it to be called. This will allow us to set the callback in the constructor for Xyz
:
abstract class Abc {
final _list = <String>[];
Function(String) _addedValue;
void add(String s) {
_list.add(s);
if (this._addedValue != null) this._addedValue(s);
}
void setCallback(Function(String) callback) => _addedValue = callback;
}
class Xyz extends Abc {
String _data = '';
Xyz() {
setCallback(_added);
}
void _added(String s) {
_data += '$s,';
print('data: $_data');
}
}
main() {
var a = Xyz();
a.add('hello');
a.add('goodbye');
a.addedValue('a'); // No longer possible
a.addedValue = null; // No longer possible
}
I did also make the following solution but it is so ugly and totally stupid that I needed to make another more sensible solution to present first... But I will say it "works" if the intention are also to confuse other people.
The concept of the following implementation is you instead of saving a variable to the callback, you are saving a variable to a method which can give the callback method.
abstract class Abc {
final _list = <String>[];
Function(String) Function(Abc) _getCallback;
Abc(this._getCallback);
void add(String s) {
_list.add(s);
if (this._getCallback != null && this._getCallback(this) != null)
this._getCallback(this)(s);
}
}
class Xyz extends Abc {
String _data = '';
Xyz() : super((obj) => obj is Xyz ? obj._added : null);
void _added(String s) {
_data += '$s,';
print('data: $_data');
}
}
main() {
var a = Xyz();
a.add('hello');
a.add('goodbye');
a.addedValue('a'); // No longer possible
a.addedValue = null; // No longer possible
}