Reputation: 309
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?
Upvotes: 1
Views: 910
Reputation: 309
This was something I came up.
abstract class Abc {
final _list = <String>[];
//final Function(Abc, String) _addedValue;
final dynamic _addedValue;
Abc(this._addedValue);
void add(String s) {
_list.add(s);
if (this._addedValue != null) this._addedValue(this, s);
}
}
class Xyz extends Abc {
String _data = '';
Xyz() : super(Xyz._added);
static void _added(Xyz instance, String s) {
instance._data += '$s,';
print('data: ${instance._data}');
}
}
main() {
var a = Xyz();
a.add('hello');
a.add('goodbye');
}
I'd like to be able to type _addedValue
correctly in Abc
but dynamic
was the only way I could get it to work. Tried covariant
but that's not allowed in this case.
Upvotes: 0
Reputation: 31219
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
}
Upvotes: 1