dart基础2
1.类
Dart是一种基于类和mixin继承机制的面向对象的语言。所有的类都继承于Object。基于Mixin机制意味着每个类都只有一个超类(除Object外),一个类中的代码可以在其它多个继承类中反复使用。
在Dart2中,new关键字是可选的。
在dart中,存在像下面这样实例化对象的方式:
1 | var p1 = Point(2,3); |
2.常量构造函数
在构造函数名之前加const关键字,来创建编译时常量,构造两个相同的编译时常量会产生一个唯一的,标准的实例:
1 | var a = const ImmutablePoint(1, 1); |
3.一个不太明白的特性:在dart2中,一个常量上下文中的const关键字可以被省略。如下所示:
1 | // 首先是一个不省略的版本 |
4.获取对象的类型
使用对象的runtimeType属性可以在运行的时候获取对象的类型。他返回的是一个Type对象。
5.实例变量:就是不是类对象所拥有的,而是类所实例化出来的对象所拥有的
所有未初始化变量的默认值都是null,所有实例变量都会生成一个隐式的getter方法,非final的实例变量同样会生成一个隐式的setter方法。也就是说对一个实例变量进行赋值的时候,实际都是通过调用setter方法来赋值的。
1 | class Point { |
6.构造函数,通过创建一个和类同名的函数来声明构造函数,可以使用this关键字来获取当前实例。
1 | // 很常见的生成构造函数 |
下面是精简模式:
1 | class Point { |
在没有声明构造函数的情况下,Dart会提供一个默认的构造函数,默认构造函数没有参数并会调用父类的无参构造函数。子类不会继承父类的构造函数,子类不声明构造函数,那么它就只有默认构造函数。
7.命名构造函数,使用命名构造函数可以为一个类实现多个构造函数,可以使用命名构造函数来更清晰的表明函数意图:
1 | class Point { |
8.什么鬼super,如下所示
1 | class Person { |
9.初始化列表概念,很难看
1 | class Point { |
上面这种初始化列表的写法起的作用对应了js里面的参数默认值,在写法上后者简直不要太简单优雅;在dart中,我们可以在构造函数后面加上一个:后面跟上一些初始化列表语句,同时也能够对其进行开发期assert判断处理。
10.重定向构造函数,在某些情况下,某些命名构造函数只需要使用其它构造函数的逻辑即可,那么此时使用重定向构造函数便很合适:
1 | class Point { |
11.常量构造函数,常量构造函数所创建出来的实例并不是常量(??),如果希望实例出来的变量是固定不变的话,那么首先构造函数得是const的,并且所有实例变量也都得是final。如下所示:
1 | class ImmutablePoint { |
12.工厂构造函数,第一次接触到。如果类中的某个构造函数并不总是返回这个类的实例(而是有可能返回其它类的实例)的话,那么这个构造函数也被叫做工厂构造函数,使用factory关键字来定义,如下所示:
1 | class Logger { |
13.Getters和Setters,每一个实例变量都会有一个隐式的getter,通常也会有一个setter。同时我们也可以使用get和set关键字来显式设置getters和setters。
1 | class Rectangle { |
14.抽象方法,抽象方法只能够存在于抽象类中。实例方法,getter,setter方法可以是抽象的,他们只定义接口而不实现,实现交给子类去完成。调用抽象方法会带来运行时错误:
1 | abstract class Doer { |
15.抽象类:使用abstract修饰符来定义一个抽象类,抽象类不能用来实例化,如果希望抽象类能够被实例化,那么可以通过定义工厂实例函数来实现。在dart中声明抽象方法无需加上abstract修饰符,没有大花括号并且加上返回值就是了。抽象方法只能在抽象类中定义。
1 | abstract class AbstractContainer { |
16.接口:每个类都隐式的定义了一个接口,接口包含了该类所有的实例变量以及实例方法,但是,注意并不包含构造函数。如果想要创建一个A类,并且A类要支持B类的API的话,但是又不想继承B类的实现的话,那么可以通过让A类来实现B类的接口。如下所示:
1 | class Person { |
同时一个类也能够用来实现多个接口,如下所示:
class Point implements PointA, PointB {…}
17.枚举类型是一种特殊的类,使用enum关键字来定义一个枚举类。枚举中的每一个值都具有一个index getter方法,该方法这个值在枚举类型中的位置;每个枚举类型,都具有一个values实例常量,用来获取所有枚举值列表。
1 | enum Color { red, green, blue } |
18.使用mixins,使用类的时候with一个mixin,怎么实现一个mixin?使用mixin关键字进行定义,写法和类写法一样,除了使用mixin代替了class外。
19.静态变量和静态方法,使用static即可,注意,静态变量只有在被使用的时候才会初始化;静态方法因为不可以在实例上访问,所以无法访问this。
20.泛型,挺好的
1 | var names = List<String>(); |
21.参数化字面量,作用是不用去猜?
1 | var names = <String>['haha', 'hai']; |
22.在运行时能够测试到泛型类型,泛型类型是固化的
1 | var names = List<String>(); |
23.限制泛型类型
1 | class Foo<T extends SomeBaseClass> { |
24.泛型方法,这才像样
1 | T first<T>(List<T> ts) { |
25.库和可见性,import和library指令用来创建模块化的,可共享的代码库。以下划线_开头的标识符仅在库中可见,每个dart程序都是一个库,尽管没有使用library指令。
利用import命令来使用一个库,import后面加上一个URI;对于内置的库来说,URI拥有自己内置的dart:方案;对于其他的库,使用系统文件路径或者package:方案;其中后者使用package:方案是指定由包管理器(pub工具)所提供的库。如下所示:
1 | import 'dart:html'; |
26.指定库前缀来解决两个库里面定义了同一个类;假设下面两个类中都有Element的声明的话,那么如下所示:
1 | import 'package:lib1/lib1.dart'; |
27.导入库的一部分,还是挺方便的,如下所示:
1 | import 'package:lib1/lib1.dart' show foo; // 只导入这个库的foo部分 |
28.延迟加载库,在某些地方还是能够派上用场的,使用延迟加载库的功能能够优化App启动时间;延迟加载库使用上了dart的异步功能,如下所示:
1 | import 'package:greetings/hello.dart' deferred as hello; |