Dart Language Tour 学习笔记1

本文深入讲解Dart语言的基础知识,包括变量与内置类型、字符串、列表、集合、映射、函数及匿名函数的使用,以及如何创建常量和不可变对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

变量和内置的类型


Final and const

  • 如果您从不打算更改变量,请使用final或const,而不是var或者一个类型。 final变量只能设置一次; const变量是编译时常量。 (Const变量是隐式final的。)final的顶级或类变量在第一次使用时被初始化
  • 实例变量可以是final的,但是不能是const的,且final的实例变量必须在构造函数前初始化
  • const修饰符不仅可以修饰变量,还可以修饰一个常量值,以及修饰一个创建常量值的构造函数;任何变量都可以被赋予一个const常量值
//const修饰变量
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere

//const修饰常量值
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`
  • 在创建const常量的声明时,可以省略赋值时的初始化表达式中的const,比如上面的baz常量的创建

  • 即使一个非final和非const的变量曾经被赋值了一个const常量,但是还是可以改变其值;相反,const修饰的常量不能被修改值

  • 一个类能够定义 const 构造函数的前提是成员变量必须都是用final或const修饰的,调用该构造函数时,用const代替new,表示对象的状态完全可以在编译期间确定,并且完全是不可变的
    在这里插入图片描述

  • const导致的不可变性是可传递的,如果你有一个final修饰的成员变量,这个成员变量包含了一个集合,那么这个集合仍然是可变的。如果包含的是const修饰的集合,那么集合内的所有东西是递归地不可变的
    在这里插入图片描述
    第一处打印[4,2,3],第二处打印将会报错

  • 相同的const变量不会在内存中重复创建,如果表达式被调用了多次,则重用之前创建好的常量,那可以理解成const修饰的常量是单例模式吗?(按照原作者的回复,由于const的不可变性,所以这里的还不仅仅是单例,且是运行时不可以修改的单例)


String

  • Dart中的string是utf-16编码的
  • 字符串可以使用单引号,也可以使用双引号
  • 字符串拼接可以使用+ ,也可以直接将相邻的两个拼接:
var s1 = 'String '
    'concatenation'
    " works even over line breaks.";
assert(s1 ==
    'String concatenation works even over '
        'line breaks.');

var s2 = 'The + operator ' + 'works, as well.';
assert(s2 == 'The + operator works, as well.');
  • 创建多行字符串还可以使用三个单引号或者三个双引号开始并结尾:
var s1 = '''
You can create
multi-line strings like this one.
''';

var s2 = """This is also a
multi-line string.""";
  • 文字字符串是编译时常量,只要任何插值表达式是一个编译时常量,其值为null或数值,字符串或布尔值。
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];

const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';

Lists

Dart中的数组是List类型的对象,所以很多人就直接称其为lists,
var list = [1, 2, 3];
上面的list类型是List<int>,所以添加非int类型的元素会编译报错

  • 创建一个编译时的常量list,需要在常量字面值之前添加const,当然,这之后,该变量是无法修改其中的数组元素值的:
var constantList = const [1, 2, 3];
// constantList[1] = 1; // Uncommenting this causes an error.

spread operator (…) 和null-aware spread operator (…?)

在Dart2.3中,加入了传播操作符… ,和空感知的传播操作符?..
这提供了一种插入多个元素到一个集合中的简便方式:

var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);

var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
  • 从Dart2.3开始,可以使用‘if’和‘for’条件语句来创建集合,如:
var nav = [
  'Home',
  'Furniture',
  'Plants',
  if (promoActive) 'Outlet'
];

var listOfInts = [1, 2, 3];
var listOfStrings = [
  '#0',
  for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');

Set

Dart中的set集合是无序、且元素不可重复的,在Dart 2.2开始,加入了Set 字面值,下面使用set literal字面值创建了一个set,集合类型为Set<String>

var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.  it's type is Map<dynamic, dynamic>.
  • Dart先引入了map, 所以看似set和map的语法相似,以上创建空的集合时,不指明类型,Dart默认其类型为 Map<dynamic, dynamic>
  • 创建一个编译时常量set集合,可以在set集合字面值前添加const:
final constantSet = const {
  'fluorine',
  'chlorine',
  'bromine',
  'iodine',
  'astatine',
};
// constantSet.add('helium'); // Uncommenting this causes an error.

Maps

Dart中的map,key可以是任何类型;创建一个编译时常量map,可以在map字面值前添加const:

//直接创建一个map
var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

//使用构造函数创建map
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';

//创建编译时常量
final constantMap = const {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

Runes

Dart中的字符串是UTF-16编码的,在转换为32位的Unicode编码时,需要特定的语法
在这里插入图片描述

Functions

  • 定义命名参数函数时,参数列表要用{ } 括起来,可指定@required注解标明该可选命名参数是必须要传值的:
const Scrollbar({Key key, @required Widget child})

Optional parameters

  • Optional parameters can be either named or positional, but not both.

  • 将可选的函数参数用[ ]括起来,以此表示括号中的参数是可选的:

String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
  • 给可选参数赋初始值时,必须要是编译时常量,集合前要用const
void doStuff(
    {List<int> list = const [1, 2, 3],
    Map<String, String> gifts = const {
      'first': 'paper',
      'second': 'cotton',
      'third': 'leather'
    }}) {
  print('list:  $list');
  print('gifts: $gifts');
}

cascades级联操作符

  • cascades级联操作符以… 表示,可以在一个对象的成员上进行多次操作:
void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}

Dart中的函数是一等公民(变量也是可以直接在一个文件中直接定义)

  • 可以将函数作为参数传入方法中,或者赋值给一个变量
void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);

//将一个函数赋值给一个变量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

匿名函数

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

如果匿名函数的参数只有一个,可以使用=>代替大括号{ },如:

list.forEach(
    (item) => print('${list.indexOf(item)}: $item'));
  • 将函数作为返回值
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

void main() {
  // Create a function that adds 2.
  var add2 = makeAdder(2);

  // Create a function that adds 4.
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值