В чем разница между именованными и позиционными параметрами в Dart?

Dart поддерживает как именованные необязательные параметры, так и позиционные необязательные параметры. В чем разница между ними?

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


person Seth Ladd    schedule 07.11.2012    source источник
comment
Случай необязательных именованных параметров - я использую класс dart во флаттере, а его код выглядит следующим образом: class MyDataObject {final int anInt; final String aString; финальный дабл aDouble; MyDataObject ({this.anInt = 1, this.aString = 'Старый!', This.aDouble = 2.0,}); } появляется сообщение об ошибке "Добавить необходимое ключевое слово" перед this.anInt = 1, this.aString = 'Old!' and this.aDouble = 2.0, Пожалуйста, подскажите, в чем проблема и как мы можем ее исправить. Спасибо.   -  person Kamlesh    schedule 25.05.2021


Ответы (6)


В Dart есть два типа необязательных параметров: именованные и позиционные. Прежде чем обсуждать различия, позвольте мне сначала обсудить сходства.

Необязательные параметры Dart являются необязательными в том смысле, что от вызывающей стороны не требуется указывать значение параметра при вызове функции.

Необязательные параметры могут быть объявлены только после любых обязательных параметров.

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

Позиционные необязательные параметры

Параметр, заключенный в [ ], является позиционным необязательным параметром. Вот пример:

getHttpUrl(String server, String path, [int port=80]) {
  // ...
}

В приведенном выше коде port является необязательным и имеет значение по умолчанию 80.

Вы можете вызвать getHttpUrl с третьим параметром или без него.

getHttpUrl('example.com', '/index.html', 8080); // port == 8080
getHttpUrl('example.com', '/index.html');       // port == 80

Вы можете указать несколько позиционных параметров для функции:

getHttpUrl(String server, String path, [int port=80, int numRetries=3]) {
  // ...
}

Необязательные параметры являются позиционными в том смысле, что вы не можете пропустить port, если хотите указать numRetries.

getHttpUrl('example.com', '/index.html');
getHttpUrl('example.com', '/index.html', 8080);
getHttpUrl('example.com', '/index.html', 8080, 5);

Конечно, если вы не знаете, что такое 8080 и 5, трудно сказать, что это за магические числа. Вы можете использовать именованные необязательные параметры для создания более удобочитаемых API.

Именованные необязательные параметры

Параметр, заключенный в { }, является именованным необязательным параметром. Вот пример:

getHttpUrl(String server, String path, {int port = 80}) {
  // ...
}

Вы можете вызвать getHttpUrl с третьим параметром или без него. Вы должны использовать имя параметра при вызове функции.

getHttpUrl('example.com', '/index.html', port: 8080); // port == 8080
getHttpUrl('example.com', '/index.html');             // port == 80

Вы можете указать несколько именованных параметров для функции:

getHttpUrl(String server, String path, {int port = 80, int numRetries = 3}) {
  // ...
}

Поскольку на именованные параметры ссылаются по имени, их можно использовать в порядке, отличном от их объявления.

getHttpUrl('example.com', '/index.html');
getHttpUrl('example.com', '/index.html', port: 8080);
getHttpUrl('example.com', '/index.html', port: 8080, numRetries: 5);
getHttpUrl('example.com', '/index.html', numRetries: 5, port: 8080);
getHttpUrl('example.com', '/index.html', numRetries: 5);

Я считаю, что именованные параметры упрощают понимание сайтов вызовов, особенно когда есть логические флаги или числа вне контекста.

Проверка наличия необязательного параметра

К сожалению, вы не можете различить случаи «необязательный параметр не был предоставлен» и «необязательный параметр был предоставлен со значением по умолчанию».

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

thisFunctionWontWork(String foo, [String positonal], {String named}) {
  // will not work!
}
person Seth Ladd    schedule 07.11.2012
comment
? оператор устарел. В учебнике по дартсу я нашел только условие scale == null. (expr1? expr2: expr3 все еще работает) - person Zdeněk Mlčoch; 30.11.2013
comment
Люблю несколько именованных параметров для функции, это было трудно найти! Будет ли еще лучше смотреться в части документов, посвященной конструкторам? ;) - person Will Squire; 10.12.2014
comment
Значения по умолчанию теперь должны быть указаны с = вместо :, согласно dartlang.org/guides/language/. - person nbro; 14.08.2017
comment
Почему нельзя использовать как позиционные необязательные параметры, так и именованные необязательные параметры. - person Donghua Liu; 16.09.2020
comment
Исторически, какой из них был впервые реализован Dart Team, позиционные или именованные необязательные параметры? Моя гипотеза: первая реализованная - это позиционные необязательные параметры. - person Let Me Be Your Lost Disciple; 12.10.2020
comment
Случай необязательных именованных параметров - я использую класс dart во флаттере, а его код выглядит следующим образом: class MyDataObject {final int anInt; final String aString; финальный дабл aDouble; MyDataObject ({this.anInt = 1, this.aString = 'Старый!', This.aDouble = 2.0,}); } появляется сообщение об ошибке "Добавить необходимое ключевое слово" перед this.anInt = 1, this.aString = 'Old!' and this.aDouble = 2.0, Пожалуйста, подскажите, в чем проблема и как мы можем ее исправить. Спасибо. - person Kamlesh; 25.05.2021
comment
Пожалуйста, предложите Null Satety. Спасибо. - person Kamlesh; 25.05.2021
comment
Для ясности: вы можете потребовать именованные параметры, используя необходимое ключевое слово, например: {required String name} - person CoderBlue; 10.06.2021

В Dart, насколько я понимаю, параметр метода может быть двух типов.

  • Обязательный параметр
  • Необязательный параметр (позиционный, именованный и по умолчанию)

>> Обязательный параметр

Обязательный параметр - это хорошо известный параметр старого стиля, с которым мы все знакомы.

пример:

findVolume(int length, int breath, int height) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,30);

вывод:

length = 10, breath = 20, height = 30

>> Дополнительный позиционный параметр

Параметр будет заключен в квадратную скобку [], а параметр в квадратных скобках не обязателен.

пример:

findVolume(int length, int breath, [int height]) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,30);//valid
findVolume(10,20);//also valid

вывод:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = null // no value passed so height is null

>> Необязательный именованный параметр

  • параметр будет отображаться в фигурной скобке {}
  • параметр в фигурных скобках не является обязательным.
  • необходимо использовать имя параметра, чтобы присвоить значение, разделенное двоеточием :
  • в фигурных скобках порядок параметров не имеет значения
  • эти параметры типа помогают нам избежать путаницы при передаче значения для функции, которая имеет много параметров.

пример:

findVolume(int length, int breath, {int height}) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,height:30);//valid & we can see the parameter name is mentioned here.
findVolume(10,20);//also valid

вывод:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = null

>> Необязательный параметр по умолчанию

  • так же, как необязательный именованный параметр, кроме того, мы можем присвоить этому параметру значение по умолчанию.
  • Это означает, что значение не передается, будет использоваться значение по умолчанию.

пример:

findVolume(int length, int breath, {int height=10}) {
 print('length = $length, breath = $breath, height = $height');
} 

findVolume(10,20,height:30);//valid
findVolume(10,20);//valid 

вывод:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = 10 // default value 10 is taken

Спасибо за четкое объяснение, данное по этой ссылке на видео, спасибо создателю видео.

ссылка на видео: OptionalPositionalParameters

ссылка на видео: OptionalNamedParameters

ссылка на видео: OptionalDefaultParameters

person SaravanaRaja    schedule 26.04.2019
comment
Случай необязательных именованных параметров - я использую класс дротика во флаттере, а его код выглядит следующим образом: class MyDataObject {final int anInt; final String aString; финальный дабл aDouble; MyDataObject ({this.anInt = 1, this.aString = 'Старый!', This.aDouble = 2.0,}); } появляется сообщение об ошибке "Добавить необходимое ключевое слово" перед this.anInt = 1, this.aString = 'Old!' and this.aDouble = 2.0, Пожалуйста, подскажите, в чем проблема и как мы можем ее исправить. Спасибо. - person Kamlesh; 25.05.2021
comment
Требуется ваше предложение о нулевой безопасности. Спасибо. - person Kamlesh; 25.05.2021

Позиционные параметры:

Они такие же, как параметры по умолчанию. Например:

void add(int x, [int y = 3]);

Здесь y имеет значение по умолчанию 3

Именованные параметры:

Это параметры, которые можно передавать в любом порядке, передав имя параметра, за которым следует переданное значение. Например:

void sum({int num1, int num2});

Эта функция вызывается так:

sum(num1: 12, num2: 24);

Также именованные параметры могут иметь значения по умолчанию.

person Zohaib Hamdule    schedule 19.06.2020

Когда параметр функции указывается с использованием синтаксиса «paramName: value», то это именованный параметр. Такие параметры можно сделать необязательными, заключив их в квадратные скобки [и]. Простую демонстрацию этой функции можно продемонстрировать в следующей программе Hello World:

sayHello([String name = ' World!']) {
  print('Hello, ${name}');
}

void main() {
  sayHello('Govind');
}
person Balepur    schedule 29.09.2018

Dart имеет два типа параметров функции: positional и named.

Необязательные позиционные параметры

Позиционные параметры вам наверняка знакомы:

int sumUp(int a, int b, int c) {
  return a + b + c;
}
// ···
  int total = sumUp(1, 2, 3);

В Dart вы можете сделать эти позиционные параметры необязательными, заключив их в квадратные скобки:

int sumUpToFive(int a, [int b, int c, int d, int e]) {
  int sum = a;
  if (b != null) sum += b;
  if (c != null) sum += c;
  if (d != null) sum += d;
  if (e != null) sum += e;
  return sum;
}
// ···
  int total = sumUpToFive(1, 2);
  int otherTotal = sumUpToFive(1, 2, 3, 4, 5);

Необязательные позиционные параметры всегда идут последними в списке параметров функции. Их значение по умолчанию равно null, если вы не укажете другое значение по умолчанию:

int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {
// ···
}
// ···
  int newTotal = sumUpToFive(1);
  print(newTotal); // <-- prints 15

Code example

Реализуйте функцию с именем joinWithCommas(), которая принимает от одного до пяти целых чисел, а затем возвращает строку этих чисел, разделенных запятыми. Вот несколько примеров вызовов функций и возвращаемых значений:

String joinWithCommas(int a, [int b, int c, int d, int e]) {
  var total = '$a';
  if (b != null) total = '$total,$b';
  if (c != null) total = '$total,$c';
  if (d != null) total = '$total,$d';
  if (e != null) total = '$total,$e';
  return total;
}

Вызов функции

joinWithCommas(1)       
joinWithCommas(1, 2, 3)     
joinWithCommas(1, 1, 1, 1, 1)

Возвращаемое значение

'1'
'1,2,3'
'1,1,1,1,1'

Необязательные именованные параметры

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

void printName(String firstName, String lastName, {String suffix}) {
  print('$firstName $lastName ${suffix ?? ''}');
}
// ···
  printName('Avinash', 'Gupta');
  printName('Poshmeister', 'Moneybuckets', suffix: 'IV');

Как и следовало ожидать, значение этих параметров по умолчанию равно null, но вы можете указать значения по умолчанию:

void printName(String firstName, String lastName, {String suffix = ''}) {
  print('$firstName $lastName $suffix');
}

Функция не может иметь как необязательные позиционные, так и необязательные именованные параметры.

Пример кода

Добавьте метод экземпляра copyWith() в класс MyDataObject. Он должен принимать три именованных параметра:

int newInt
String newString
double newDouble

При вызове copyWith() должен возвращать новое MyDataObject на основе текущего экземпляра с данными из предыдущих параметров (если таковые имеются), скопированными в свойства объекта. Например, если newInt не равно нулю, скопируйте его значение в anInt.

class MyDataObject {
  final int anInt;
  final String aString;
  final double aDouble;

  MyDataObject({
     this.anInt = 1,
     this.aString = 'Old!',
     this.aDouble = 2.0,
  });

  // Add your copyWith method here:
}
person Paresh Mangukiya    schedule 22.01.2021
comment
появляется сообщение об ошибке, которое необходимо "Добавить необходимое ключевое слово" перед this.anInt = 1, this.aString = 'Old!' and this.aDouble = 2.0, Пожалуйста, подскажите, в чем проблема и как мы можем ее исправить. Спасибо. - person Kamlesh; 25.05.2021
comment
Требуется ваше предложение о нулевой безопасности. Спасибо. - person Kamlesh; 25.05.2021

Из doc мы получаем, что оба параметра positional и named являются необязательными. , что означает, что все они могут отсутствовать.

На мой взгляд, named параметры строже, чем positional. Например, если вы объявите такой метод:

String say({String from, String msg})

Выше from и msg - параметры named, когда вы вызываете метод say, вы должны использовать say(from: "xx", msg: "xx"). Ключи не могут отсутствовать.

Однако если вы используете позиционные параметры, вы свободны.

person CoXier    schedule 07.01.2019
comment
В документе говорится: ›Необязательные параметры могут быть именованными или позиционными, но не обоими сразу. Где сказано, что позиционные параметры необязательны? - person Markon; 16.08.2019
comment
Позиционный параметр - это стиль параметров по умолчанию в языках программирования, который называется позиционным, потому что это первый параметр или второй и т. Д. Named параметры называются так, потому что вы можете фактически идентифицировать их по имени, а не по положению (если вы переключите положение двух названных параметров, это не имеет значения). См. Ответ Саваранараджи выше - person Markon; 16.08.2019