函数是Dart中的一等值,它们能被保存在变量中,能作为参数传递及作为函数的返回值。与所有Dart运行时的值一样,函数同样是对象。

函数总是有一个形式参数列表,虽然这个参数列表可能为空。参数要么是位置型的,要么是命名型的。

可选参数必须排列在一起放置在参数列表尾部并用方括号包裹。任意必填参数都必须出现在可选参数前面。可选参数可以指定默认值但必须为编译时常量。

increment(x, [step = 1]) => x+step;

命名参数要在位置参数之后声明并用大括号包裹。命名参数始终是可选的。换而言之,对参数的分类如必填或可选,与参数的位置或命名的分类是没有关联的。你不能混合使用可选位置参数与命名参数,你只能使用其中一种。

函数体从第1条语句开始执行,直到以下任意一种情况发生:函数最后一条语句被成功执行,一个return语句被执行,或是抛出了一个没有被捕获的异常。Dart中的每个函数要么返回一个值,要么抛出一个异常。如果完成了最后一条语句,而且它不是return,则将返回null

构造函数是用来创建类的实例的特殊函数。构造函数包括了工厂构造函数与生产构造函数,其中工厂函数是具备特殊功能的普通函数。生产构造函数与工厂构造函数的区别在于,它始终返回一个新的实例或抛出一个异常。所以就算是没有显式地使用return语句,生产构造函数也不会返回null。实际上,生产构造函数不能返回任何表达式,它只可能包含一个没有关联表达式的return语句。

函数声明有一个函数名称,后面跟着参数列表和函数体。抽象方法有函数签名但是没有函数体。函数声明可以出现在顶层或是作为方法存在,函数也可以是局部函数。局部函数就是定义在其他函数内部的函数。

函数可以定义在表达式内部,它们被称为函数字面量,或者被更笼统地称为闭包。与函数声明不同,闭包没有名称。虽然如此,与其他函数一样,它们也有参数列表与函数体。

有些函数被称为getter,可以不使用参数列表来调用。true.runtimeType

getter与方法是通过不同的语法访问的。因此,Dart开发者需要注意一个函数是被声明为getter还是一个无参数的方法。这种情况同样适用于setter。

Dart支持使用双点运算符进行方法级联。当需要对一个对象执行一系列的操作时,级联是非常有用的。级联的求值过程就像普通的方法调用,只是它的值不是方法调用的返回值,而是当前对象。

`new Address.of("Solarex")..setStreet("Shekou")..city = "shenzhen" ..zipCode(66666, extend: 88888);

v = e这样的赋值操作,其确切含义取决于v的声明。如果v是局部变量或参数,那么这就只是一个传统的赋值。否则,这个赋值只是对调用名为v=setter的语法糖而已。

Dart支持用户自定义运算符,这些方法必须使用内置标识符operator作为前缀。允许自定义的运算符有<><=>===-+/~/*%|^&<<>>[]=[]~。此外,还有一些固定的运算符不允许开发者自定义,它们是&&||及自增和自减运算符++(包括作为前缀与后缀)。

赋值并不认为是一个运算符,虽然复合赋值的语义会依赖于运算符。

Function是代表所有函数的公共顶层接口的抽象类。Function没有声明任何实例方法。然而它声明了类方法applyapply的签名是

static apply(Function function, List positionalArguments, [Map<Symbol, dynamic> namedArguments]);

apply()提供了一种使用动态确定的参数列表来调用函数的机制。通过它,可以处理在编译时参数列表数量不确定的情况。

所有真正的函数都隐含支持一个签名跟函数本身一致的call()方法,它的作用是执行当前的函数。f(1)实际上是f.call(1)

任何声明了call()方法的类都被认为隐含实现了Function类。注意Function类没有声明call()方法。原因是没有特定的函数签名来声明。

Dart中所有运行时的值都是对象,包括函数,除了call()方法,函数也支持所有在Object中声明的方法。

实际上,一个函数表达式每被计算一次,就可能重新分配一个新的函数对象。同样,局部函数的声明每次被新的动态作用域包含时,就会引入一个新的对象。

Dart运行时的各种类都可以用来表示函数。所有这些类都将实现Function,但对于不同函数的运行时类型,不能指望在它们之间执行相等与相同检测。

Dart支持生成器,它是用来产生集合值的函数。生成器可以是同步或异步的。同步的生成器为迭代器生成提供语法糖,而异步的生成器则为流的生成提供语法糖。

支持通过迭代器进行迭代的集合被称为可迭代对象,可迭代对象必须有一个名为iterator的用于返回迭代器的getterfor-in循环可以操作任意可迭代对象。

迭代器与可迭代对象的接口分别被类IteratorIterable实现。

可以给函数体使用sync*修饰符来定义生成器函数:

naturalsToSync(n) sync* {
  var k = 0;
  while (k < n) yield k++;
}

被调用时,此函数将立即返回一个可迭代对象i,i又包含了迭代器j。在迭代器j的moveNext()第一次被调用时,此函数才开始执行。在进入循环后,yield语句被执行,导致k被加1,而上一次k的值被追加到i同时naturalsToSync的执行将暂停。在下一次moveNext被调用时,暂停yieldnaturalsToSync将继续执行同时循环将重复。

需要牢记一点,生成器函数的函数体是在函数返回一个结果给调用者后才开始执行的,那生成器内return扮演的事什么角色?答案就是return会直接终止生成器。在生成器中我们不能使用return语句来返回值,这样的语句将被编译器标记为错误。

同步生成器中的yield语句将对象追加到与之关联的可迭代对象,并暂停函数体的执行。

与其他运行时的值一样,Dart函数是对象。Dart中的函数可以声明为接收位置或命名参数。位置参数可以是必填或可选的,命名参数始终是可选的。

Dart函数既能作为类的方法也能作为独立的结构。方法可以与实例(实例方法)或类(类方法)关联。独立的函数可以在库级别进行声明(顶层函数),也可以通过函数声明或字面表达式称为其他函数内的本地函数。

所有内置的操作符也都是函数,且它们大部分都被定义为实例方法,可以被开发者重写。用户定义的类可以通过实现特殊的call方法来模拟内置函数类型。所有Dart函数都被认为是Function类型的成员。

results matching ""

    No results matching ""