Dart - Разрешить любые параметры для базового метода

Мне нужен базовый метод, который может принимать любые параметры. Можете ли вы сделать это, не создавая новый класс для параметра? Я думаю, что единственный способ - указать один параметр и создать тип для этого параметра? Итак, я сделал это:

Метод в базовом классе:

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» не определен для типа «Объект».

Могу ли я использовать дженерики, чтобы сделать его типобезопасным, или, что еще лучше, вообще избегать строгой типизации и просто передавать что-либо?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
145
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы ищете языковую функцию «Переменное количество аргументов функции» (например, это в 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();

Спасибо, это выглядит красиво. Работает ли это с передачей в пустоту, когда нет аргументов? Мне пришлось удалить extends Args из вашего решения, чтобы разрешить передачу типа void, и сделать это: `@override void onSubmitPressed(void args) { super.onSubmitPressed(args);`. Кажется немного неудобным явно передавать пустые аргументы, но так ли это необходимо?

BeniaminoBaggins 16.12.2020 03:15

Да, вы можете использовать void. extends Args удалять не обязательно, смотрите мой обновленный ответ.

Mol0ko 16.12.2020 08:22

Спасибо. Он жалуется, что Class2 не дает общий тип для BaseClass. Он жалуется дважды: «динамический» не расширяет «Args». Попробуйте использовать тип, который является или является подклассом «Args». А также: Тип «Класс2» объявлен с 2 параметрами типа, но был задан 1 аргумент типа. Попробуйте настроить количество аргументов типа так, чтобы оно соответствовало количеству параметров типа. (К вашему сведению, у меня есть другой параметр типа, поэтому он сказал 2 параметра типа).

BeniaminoBaggins 16.12.2020 08:41

О да, наконец, вы были правы насчет extend Args, потому что dynamic или void не расширяют 'Args'. Давайте попробуем удалить общее ограничение. Что касается Class2 is not giving a type generic to BaseClass - это ошибка времени выполнения или проблема статического анализатора?

Mol0ko 16.12.2020 08:48

я могу найти его здесь? dart-lang.github.io/linter/lints

Mol0ko 16.12.2020 08:54

Нет, это "wrong_number_of_type_arguments", которого там нет

BeniaminoBaggins 16.12.2020 08:57

У меня такого предупреждения нет, поэтому, к сожалению, мне будет сложно найти причину(

Mol0ko 16.12.2020 09:03

Возможно другая версия: Flutter 1.22.4 • канал стабильный • github.com/flutter/flutter.git Framework • ревизия 1aafb3a8b9 (5 недель назад) • 2020-11-13 09:59:28 -0800 Engine • ревизия 2c956a31c0 Инструменты • Дарт 2.10.4

BeniaminoBaggins 16.12.2020 09:05

Другие вопросы по теме