Dart方法有两种类型的参数:必需的和可选的。必需的咱们通常都知道,这里主要分析可选参数。算法
若是同时包含可选参数和必需参数,必需的参数在参数列表前面, 可选数在后面。bash
可选参数能够有一个默认值,当默认值在调用者没有指定值时使用。这一点和kotlin的语法很像。其次可选参数具体可分为:ide
在方法参数中,使用"{}"包围的参数属于可选命名参数,好比函数
void _buildThree(int num, {String name, int range}) {
}
复制代码
能够为可选参数添加默认值,好比:工具
void _buildThree(int num, {String name, int range = 10}) {
}
复制代码
调用包含可选命名参数的方法时,须要使用paramName:value
的形式指定为哪一个可选参数赋值,好比:学习
_buildThree(10,range: 1);
复制代码
在方法参数中,使用"[]"包围的参数属于可选位置参数,好比测试
void _buildHouse(int num, [String where, int range]) {
}
void _buildHouseAndDefaultValue(int num, [String where = 'Shanghai', int range]) {
}
复制代码
调用包含可选位置参数的方法时,无需使用paramName:value
的形式,由于 可选位置参数是位置,若是想指定某个位置上的参数值,则必须前面位置的已经有值,即便前面的值存在默认值。 好比:ui
_buildHouse(10,10); //不可行的
_buildHouse(10,'shenzhen',10); //可行的
_buildHouseAndDefaultValue(10,10); //不可行的
_buildHouseAndDefaultValue(10,'shenzhen',10); //可行的
复制代码
这里特地使用两个不一样类型的可选参数做为示例,若是先后可选参数为相同类型,则会出现异常结果,而且只有在发生后才会注意到。因此这一点要特别注意。好比如下示例,假如本意是想赋值给age,但结果将会差强人意this
void _buildHouse(int num, [int range , int age]) {
print('range : $range age : $age');
}
void main() {
_buildHouse(10,10);
}
输出:
range : 10 age : null
复制代码
Dart和Java同样只支持单继承。并且Dart中没有和Java同样提供Interface字段去声明一个接口,可是也有抽象类。spa
若是想使用和Java接口同样的功能可使用Mixins
和implements
两种方式,分别解释下两种方式:
class A {
void a() {
print('a');
}
}
class B implements A {
@override
void a() {
print('override a');
}
}
class C {
void c() {
print('c');
}
}
class E {
String e = 'eeee';
}
class D extends A with C, E {
void c() {
print('c is D');
}
void d() {
c();
}
}
复制代码
首先看B implements A
,因此此时A
相对于B
来讲就是一个接口,因此他要实现B
中的方法。换句话说,Dart每一个类都是接口
而后看D extends A with C
,D
继承于A
,因为单继承特性,这个时候D
不能再使用extends
关键字继承其余类,可是可使用with
关键字折叠其余类以实现代码重用。当属性和方法重复时,以当前类为准。 好比上面例子调用D
的c()
方法打印的是 c is D
。
在学习Flutter的过程当中用到了ValueChange这个方法,是用typedef修饰的一个方法。查阅了一番资料,记录下对Typedefs的理解。
先看看官网的解释,我并无看明白这个到底有什么用,能够作什么事。
说下本身的我的理解。首先须要明确的一点是在Dart中,方法是一等对象。能够把方法当作参数调用另一个方法。 typedef 本质上为 一个方法签名提供了一个别名。官网上介绍TypeDef的时候有一句话说道:"If we change the code to use explicit names and retain type information" ,使用typedef会保留方法的类型信息。以官网的例子说明
class SortedCollection {
Function compare;
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
// All we know is that compare is a function,
// but what type of function?
assert(coll.compare is Function);
}
复制代码
当把 f 赋值给 compare 的时候, 类型信息丢失了。 f 的类型是 (Object, Object) → int (这里 → 表明返回值类型)。咱们不能使用coll.compare is int f(Object a, Object b)
判断,咱们只知道该类型是一个 Function。而使用typedef
,至关于给方法贴了一个类型标签。
我在Effective Dart中看到一条规则说到: 若是须要的只是一个回调函数,使用方法便可。 若是你定义了一个类,里面只有一个名字无心义的函数, 例如 call 或者 invoke, 这种状况最好用方法替代;
//good
typedef Predicate<E> = bool Function(E element);
//bad
abstract class Predicate<E> {
bool test(E element);
}
复制代码
前面提到的ValueChange这个方法就是做为回调函数使用,具体细节能够参考The parent widget manages the widget’s state
Dart中关于泛型的使用和Java相差不大,可是重要的一点区别是:Java 中泛型信息是编译时的,泛型类型信息在运行时被擦除。而Dart 的泛型类型是固化的,在运行时有也 能够判断具体的类型。 好比如下代码再Java中是行不通的,但在Dart中是可行的
var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
复制代码
注意
is
表达式只是判断集合的类型,而不是集合里面具体对象的类型。
import
必须参数为库 的 URI。 对于内置的库,URI 使用特殊的 dart: scheme
。 对于其余的库,你可使用文件系统路径或者 package: scheme
。 package: scheme
指定的库经过包管理器来提供, 例如 pub 工具
import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';
复制代码
若是导入的多个库具备冲突的标识符,可使用库的前缀来区分
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element(); // 使用lib1的Element.
lib2.Element element2 = new lib2.Element(); // 使用lib2的Element..
复制代码
若是只使用库的一部分功能,则能够选择须要导入的内容。
// 只导入foo.
import 'package:lib1/lib1.dart' show foo;
// 导入除了foo之外的
import 'package:lib2/lib2.dart' hide foo;
复制代码
Deferred loading可让应用在须要的时候再 加载库。 下面是一些使用延迟加载库的场景:
要延迟加载一个库,须要先使用 deferred as
来 导入:
import 'package:deferred/hello.dart' deferred as hello;
复制代码
使用的时候,使用库标识符调用 loadLibrary()
函数来加载库。注意:调用 loadLibrary()
该库只是载入一次。
使用延迟加载库的时候,请注意一下问题:
loadLibrary()
函数导入到使用 deferred as
的命名空间 中。 loadLibrary()
方法返回一个 Future
。Dart默认包含全部代码均可以使用的三个注解: @deprecated
、 @override
、 和 @proxy
。
@deprecated
注解表示函数被启用@override
注解来 代表你的函数是想覆写超类的一个函数@proxy
注解来避免警告信息能够自定义元数据注解,与Java不一样的是无需使用 @interface
关键字进行定义,只需使用普通的 class
方式声明,如
library todo;
class todo {
final String who;
final String what;
const todo(this.who, this.what);
}
复制代码
import 'todo.dart';
@todo('seth', 'make this do something')
void doSomething() {
print('do something');
}
复制代码