Мне нужен базовый метод, который может принимать любые параметры. Можете ли вы сделать это, не создавая новый класс для параметра? Я думаю, что единственный способ - указать один параметр и создать тип для этого параметра? Итак, я сделал это:
Метод в базовом классе:
void onSubmitPressed(dynamic args) {}
И расширяющий класс:
@override
void onSubmitPressed(dynamic args) {
args.passwordViewModel.email = entity.email;
args.passwordViewModel.nickName = entity.nickName;
args.controller.nextPage(
duration: const Duration(milliseconds: 800),
curve: Curves.easeInOutCubic);
putLocal();
super.onSubmitPressed(args);
}
Это вызывается так:
viewModel.onSubmitPressed(SubmitArgs(controller, passwordViewModel))
class SubmitArgs {
const SubmitArgs(this.controller, this.passwordViewModel);
final PageController controller;
final RegisterPasswordViewModel passwordViewModel;
}
Оно работает. Однако мне не очень нравится создавать класс Args. Так что я очень хочу знать, если я могу избежать этого? Кроме того, если мне нужно его создать, я могу также сделать его типобезопасным с помощью дженериков, а не просто сказать dynamic
в базе. Я пытаюсь использовать дженерики, чтобы сделать его типобезопасным, например:
void onSubmitPressed<T>(T args) {}
@override
void onSubmitPressed<SubmitArgs>(SubmitArgs args) {
args.passwordViewModel.email = entity.email;
args.passwordViewModel.nickName = entity.nickName;
args.controller.nextPage(
duration: const Duration(milliseconds: 800),
curve: Curves.easeInOutCubic);
putLocal();
super.onSubmitPressed(args);
}
Кажется, он не знает, что он расширяет базовый класс, и говорит:
Получатель «passwordViewModel» не определен для типа «Объект».
Могу ли я использовать дженерики, чтобы сделать его типобезопасным, или, что еще лучше, вообще избегать строгой типизации и просто передавать что-либо?
Если вы ищете языковую функцию «Переменное количество аргументов функции» (например, это в Kotlin), у Dart ее нет. Вот фактический запрос функции.
Вы можете использовать List как аргумент функции:
void onSubmitPressed(List<dynamic> args) {
final arg0 = args[0];
final arg1 = args[1];
}
Но, как вы заметили, этот способ не является типобезопасным. Так что лучше использовать дженерики.
Что касается дженериков, я рекомендовал вам использовать в вашем случае дженерики на уровне класса:
abstract class BaseClass<T> {
void onSubmitPressed(T args);
}
class Class1 extends BaseClass<SubmitArgs> {
@override
void onSubmitPressed(SubmitArgs args) {
// TODO: implement onSubmit
}
}
Кроме того, вы можете использовать общие ограничения для ваших классов параметров, чтобы сделать ваш код более конкретным:
abstract class Args {
const Args();
}
class SubmitArgs extends Args {
const SubmitArgs(this.controller, this.passwordViewModel);
final PageController controller;
final RegisterPasswordViewModel passwordViewModel;
}
abstract class BaseClass<T extends Args> {
void onSubmitPressed(T args);
}
Если вы не хотите передавать аргументы функции onSubmitPressed
для определенного подкласса, вы можете сделать параметр args необязательным:
abstract class BaseClass<T> {
void onSubmitPressed({T args});
}
Подкласс, у которого нет аргументов для этой функции, будет таким:
class Class2 extends BaseClass {
@override
void onSubmitPressed({void args}) {
// TODO: implement onSubmit
}
}
Вызов onSubmitPressed
без аргументов из другого места:
final class2 = Class2();
class2.onSubmitPressed();
Да, вы можете использовать void
. extends Args
удалять не обязательно, смотрите мой обновленный ответ.
Спасибо. Он жалуется, что Class2
не дает общий тип для BaseClass
. Он жалуется дважды: «динамический» не расширяет «Args». Попробуйте использовать тип, который является или является подклассом «Args». А также: Тип «Класс2» объявлен с 2 параметрами типа, но был задан 1 аргумент типа. Попробуйте настроить количество аргументов типа так, чтобы оно соответствовало количеству параметров типа. (К вашему сведению, у меня есть другой параметр типа, поэтому он сказал 2 параметра типа).
О да, наконец, вы были правы насчет extend Args
, потому что dynamic
или void
не расширяют 'Args'. Давайте попробуем удалить общее ограничение. Что касается Class2 is not giving a type generic to BaseClass
- это ошибка времени выполнения или проблема статического анализатора?
я могу найти его здесь? dart-lang.github.io/linter/lints
Нет, это "wrong_number_of_type_arguments", которого там нет
У меня такого предупреждения нет, поэтому, к сожалению, мне будет сложно найти причину(
Возможно другая версия: Flutter 1.22.4 • канал стабильный • github.com/flutter/flutter.git Framework • ревизия 1aafb3a8b9 (5 недель назад) • 2020-11-13 09:59:28 -0800 Engine • ревизия 2c956a31c0 Инструменты • Дарт 2.10.4
Спасибо, это выглядит красиво. Работает ли это с передачей в пустоту, когда нет аргументов? Мне пришлось удалить
extends Args
из вашего решения, чтобы разрешить передачу типа void, и сделать это: `@override void onSubmitPressed(void args) { super.onSubmitPressed(args);`. Кажется немного неудобным явно передавать пустые аргументы, но так ли это необходимо?