Я хочу использовать именованные параметры в Dart для ясности. Как мне обращаться с ними?
TL; DR: Именованные параметры являются необязательными в результате осознанного выбора дизайна. Кроме поддержки официального языка, есть ли способ обеспечить (и сообщить) требуемые именованные аргументы?
Я считаю чрезвычайно полезным использовать именованные параметры при определении класса. Взять, к примеру, Ability
в MMORPG:
class Ability {
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
effectDuration
и recast
содержат информацию одного и того же типа (т.е. длительность времени) и, вероятно, представлены одним и тем же типом данных. Легко перепутать, какой номер идет куда. Тем не менее, они оба являются информацией, необходимой для правильности объекта, поэтому они не могут отсутствовать во время создания экземпляра.
Я мог бы просто сломать программу с помощью try-catch, чтобы обеспечить выполнение требований этих параметров, но это не похоже на удовольствие для тех, кто использует класс и не имеет представления (если не читать документы и не понимать интуитивно, что делает класс) что они необходимы.
Есть ли способ обеспечить соблюдение требования определенных именованных параметров, одновременно информируя вызывающего абонента об этом требовании и/или помогая ему правильно его использовать?
Ответы
Ответ 1
Пакет meta предоставляет аннотацию @required
, которая поддерживается DartAnalyzer.
Флаттер часто использует это и предоставляет @required
непосредственно из import 'package:flutter/foundation.dart'
foo({@required String name}) {...}
foo(); // results in static warning
@required
не проверяет, является ли переданное значение null
или нет, только то, что значение действительно было передано на сайт вызова.
Чтобы проверить null
, вы также можете использовать assert()
для проверки переданных значений
class Ability {
Ability(this.name, this.effectDuration, this.recast) : assert(name != null), assert(effectDuration != null), assert(recast != null);
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
Ответ 2
Да, есть!
Вот пример:
class Ability {
final String name;
final Duration effectDuration;
final bool recast;
Ability({
@required this.name,
this.effectDuration = new Duration(seconds: 1),
this.recast = false,
}):
assert(name != null),
assert(effectDuration != null);
}
Вам не нужно утверждать, что имя не равно null, но оно может быть полезно для вас.
Ответ 3
Хотя вы можете использовать пакет flutter foundation
, как описано в принятом ответе, когда я работаю с классами моделей, которым не нужно знать о Flutter, я предпочитаю использовать пакет meta напрямую. Таким образом, это не создает ненужную зависимость от платформы. Это позволяет вам делиться кодом Dart даже вне Flutter.
Добавьте meta в pubspec.yaml:
dependencies:
meta: ^1.1.7
Импортируйте его в свой файл класса:
import 'package:meta/meta.dart';
Используйте аннотацию @required
в своем коде:
class Person {
String name;
int age;
Person({@required this.name, this.age,});
}
Таким образом, name
является обязательным параметром, а age
- нет.
final person = Person(name: 'Bob');