Как сделать обратный вызов из суперкласса в подкласс в дартс - PullRequest
1 голос
/ 17 апреля 2020

У меня есть абстрактный класс, который добавляет строки в список и делает некоторые другие вещи.

abstract class Abc {
  final _list = <String>[];
  Function(String) addedValue;

  void add(String s) {
    _list.add(s);
    if (this.addedValue != null) this.addedValue(s);
  }
}

В моем подклассе я хочу обратный вызов каждый раз, когда строка добавляется в список. Есть также другие подклассы, которые могут или не могут хотеть обратного вызова.

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.
}

Каков самый чистый способ предоставить суперклассу метод обратного вызова?

  • Я могу не передавайте его в конструктор, потому что это метод экземпляра.
  • Я не могу сделать его статичным c, потому что ему нужен доступ к экземпляру.
  • Я бы предпочел не раскрывать методы / установщики обратного вызова за пределами подкласса.
  • Суперкласс и подкласс не будут находиться в одной библиотеке.

Ответы [ 2 ]

0 голосов
/ 17 апреля 2020

Это было то, что я придумал.

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');
}

Я хотел бы иметь возможность набирать _addedValue правильно в Abc, но dynamic был единственным способом, которым я мог заставить его работать , Пробовал covariant, но в этом случае это не разрешено.

0 голосов
/ 17 апреля 2020

В абстрактном классе Abc можно создать метод, подобный setCallback, который позволяет устанавливать обратный вызов, но больше не позволяет ему вызываться. Это позволит нам установить обратный вызов в конструкторе для 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
}

Я также сделал следующее решение, но оно настолько уродливо и совершенно глупо, что мне нужно было найти другое более разумное решение для представим сначала ... Но я скажу, что это "работает", если намерение также состоит в том, чтобы сбить с толку других людей.

Концепция следующей реализации состоит в том, что вместо сохранения переменной в обратном вызове вы сохраняете переменная для метода, который может дать метод обратного вызова.

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
}
...