// Dart中定义一个类
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
复制代码
Dart中的类与Java中的类似,不一样的是,Dart中没有private
、public
这些成员访问修饰符。若是是类私有的成员,不但愿外面访问,只须要在成员变量以前加上一个下划线_
变为私有便可。html
以上代码,在Dart中还有一种简化写法,能够自动在构造方法中对成员变量初始化。git
// Dart中定义一个类
class Person {
String name;
int age;
// 在构造方法中初始化成员变量时,可以使用以下写法简化
Person(this.name, this.age);
// 如需处理其余变量时,也可单独对其操做
// Person(this.name, this.age, String address){
// print(address);
// }
// 注意,构造方法不能重载,以上注释掉
}
复制代码
另外还须要注意一点,Dart中没有构造方法的重载,不能写两个同名的构造方法。github
在Java中,通常不会直接在类的外部去访问类成员,一般使用setter和getter方法来操做类的成员变量。而在Dart语言中,全部类中都包含隐式的getter方法,对于非final
修饰的成员,类中还包含隐式的setter方法。这就意味着,在Dart中,你能够直接在类外部经过.
操做符访问类成员。这一特色使得Dart语法更加简洁,不会写出满屏的setXXX、getXXX方法。web
固然,不少时候咱们调用setter和getter方法并不只仅是为了赋值和访问,而是为了一些额外的处理,这时候咱们只须要使用set
与get
关键字实现setter和getter方法便可。编程
class Person {
String userName;
Person(this.userName);
// 方法名前加get关键字
String get name{
return "user:" + this.userName;
}
// 方法名前加set关键字
set name(String name){
// do something
this.userName = name;
}
}
void main() {
var p = new Person("zhangsan");
print(p.name); // user:zhangsan
p.name = "Jack";
print(p.name); // user:Jack
}
复制代码
要注意,在建立对象时,new
关键字并非必须的,能够省略不写。在写Flutter界面时,不建议写new
关键字实例化对象,由于Flutter框架中没有相似的xml语言来描述UI界面,界面也是使用Dart语言来写,在使用Dart写UI时,要保持代码的简洁和结构化,省略new
会更友好。缓存
若是没有定义构造方法,则会有一个默认的无参构造方法,而且会调用超类的无参构造方法。bash
上面已经说过,Dart类中两个同名构造方法不能重载,可是Dart语言为类新增了一种称为命名构造方法
的东西。多线程
class Person {
String userName;
int age;
Person(this.userName, this.age);
// 命名构造方法
Person.fromData(Map data) {
this.userName = data['name'];
this.age = data['age'];
}
}
void main() {
// 使用命名构造方法建立对象
var p = new Person.fromData({
"name":"Bob",
"age":19
});
print(p.userName);
}
复制代码
注意,使用命名构造方法能够为一个类实现多个构造方法,也能够更清晰的代表意图。框架
若是想提供一个状态永远不变的对像,在Dart中,咱们能够建立一个编译时常量对象,节省开销。异步
class ConstPoint {
final num x;
final num y;
// 使用const修构造方法
const ConstPoint(this.x, this.y);
// 编译时常量对象,需使用const来建立对象
static final ConstPoint origin = const ConstPoint(0, 0);
}
void main() {
print(ConstPoint.origin.x);
print(ConstPoint.origin.y);
}
复制代码
当咱们须要建立一个新的对象或者从缓存中取一个对象时,工厂构造方法就派上了用场。
class Logger {
final String name;
// 建立一个静态Map作为缓存
static final Map<String, Logger> _cache = <String, Logger>{};
// 定义一个命名构造方法,用下划线"_"修饰,将构造方法私有化
Logger._internal(this.name);
// 使用关键字factory修饰类同名构造方法
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
// 调用命名构造方法建立新对象
final logger= new Logger._internal(name);
_cache[name] = logger; // 存入缓存
return logger;
}
}
}
void main() {
var uiLog = new Logger('UI');
var eventLog = new Logger('event');
}
复制代码
有时候一个构造方法会调动类中的其余构造方法来实例化,这时候可使用构造方法重定向,
class Point {
num x;
num y;
// 同名构造方法
Point(this.x, this.y);
// 命名构造方法重定向到同名构造方法,中间使用一个冒号
Point.alongXAxis(num x) : this(x, 0);
}
复制代码
熟悉C++的朋友应该对初始化列表很了解了,Java中是没有这个特性的。
class Point {
final num x;
final num y;
final num distance;
Point(x, y)
: x = x,
y = y,
distance = sqrt(x * x + y * y){
print("这是构造方法");
}
}
void main() {
var p = new Point(2, 3);
print(p.distance);
}
复制代码
final
修饰的变量this
的这个特性,又很相似于C++中的运算符重载,在Java中是没用这种概念的。
class Point {
int x;
int y;
Point(this.x, this.y);
// 使用operator关键字,为该类重载"+"运算符
Point operator +(Point p) {
return new Point(this.x + p.x, this.y + p.y);
}
// 为该类重载"-"运算符
Point operator -(Point p) {
return new Point(this.x - p.x, this.y - p.y);
}
}
void main(){
var p1 = new Point(1,5);
var p2 = new Point(7,10);
// 重载运算符后,类可使用“+”、“-” 运算符操做
var p3 = p1 + p2;
var p4 = p2 - p1;
print("${p3.x}, ${p3.y}");
print("${p4.x}, ${p4.y}");
}
复制代码
打印结果:
8, 15
6, 5
复制代码
Dart中容许重载的运算符以下:
+ |
– |
* |
~/ |
/ |
% |
^ |
< |
> |
<= |
>= |
== |
[] |
[]= |
& |
~ |
<< |
>> |
| |
Dart中的继承,与Java中类似,可使用关键字extends
继承父类,使用关键字super
引用父类
class Father {
myFunction(){
// do something
}
}
class Son extends Father {
@override
myFunction(){
super.myFunction();
// do something
}
}
复制代码
咱们都知道,Java中的类仅支持单继承,而Dart中的类能够实现多继承。要实现多继承,须要使用with
关键字。
// 首先定义三个父类
class Father1 {
a(){
print("this is a func");
}
common(){
print("common Father1");
}
}
class Father2 {
b(){
print("this is b func");
}
common(){
print("common Father2");
}
}
class Father3 {
c(){
print("this is c func");
}
common(){
print("common Father3");
}
}
//定义子类
class Son extends Father1 with Father2,Father3{
}
void main() {
var obj = new Son();
obj.common();
obj.a();
obj.b();
obj.c();
}
复制代码
打印结果:
common Father3
this is a func
this is b func
this is c func
复制代码
要注意,以上继承写法中,也能够直接使用with
,等价于以下写法
class Son with Father1,Father2,Father3{
}
复制代码
Dart语言没有提供
interface
关键字来定义接口,可是Dart语言中保留了抽象类,同Java,使用abstract
关键字来修饰抽象类。而Dart中的抽象类,实际上就至关于Java中的接口。
abstract class Base {
// 省略函数体便可定义抽象方法,不需加关键字
func1();
func2();
}
复制代码
注意,抽象类是不能被实例化的,子类继承抽象类时,必须实现所有抽象方法。
实际上在Dart中,每一个类都隐式的定义了一个包含全部实例成员的接口, 而且该类实现了这个接口。
所以,若是咱们想实现某个接口,但有又不想继承,则可使用这种隐式接口机制。咱们须要用到关键字implements
class People {
void greet(){
print("Hello");
}
}
class Student implements People{
@override
void greet(){
print("Hi,I'm Alice.");
}
}
greet(People p){
p.greet();
}
void main() {
greet(new Student());
}
复制代码
Dart中也支持泛型,用法与Java中相似。
// 泛型
var names = new List<String>();
names.add("zhangsan")
var maps = new Map<int, String>();
maps[1]="value";
// 字面量写法
var infos = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots'
};
复制代码
若是关心具体异常,针对不一样异常进行不一样处理,可使用try...on
处理异常,finally
是可选的,用于最后的处理。
try {
// 使除数为0
print(11~/0);
} on IntegerDivisionByZeroException {
print("除数为0");
}on Exception{
print("Exception");
}finally {
print("finally");
}
复制代码
不关心具体异常,只想捕获,避免异常继续传递,则可使用try...catch
处理
try {
print(11~/0);
} catch(e){
// 打印报错信息
print(e);
}finally {
print("finally");
}
复制代码
若是想获取更多异常信息,可使用两个参数的catch
,第二个参数是异常的调用栈信息
try {
print(11~/0);
} catch(e,s){
print(s);
}
复制代码
若是你既想针对不一样异常进行不一样处理,还想打印调用栈信息,那就将两种结合起来使用
try {
print(11~/0);
} on IntegerDivisionByZeroException catch(e,s){
print(s);
} on Exception catch(e,s){
print(s);
}
复制代码
Dart使用import
语句用来导入一个库,后面跟一个字符串形式的Uri来指定表示要引用的库。
// 指定dart:前缀,表示导入标准库,如dart:io
import 'dart:math';
// 也能够用相对路径或绝对路径来引用dart文件
import 'lib/student/student.dart';
// 指定package:前缀,表示导入包管理系统中的库
import 'package:utils/utils.dart';
复制代码
导入库时,可使用as
关键字来给库起别名,避免命名空间冲突。
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// 使用lib1中的Element
Element element1 = new Element();
// 使用lib2中的Element
lib2.Element element2 = new lib2.Element();
复制代码
使用show
和hide
关键字控制库中成员的可见性
// 仅导入foo,屏蔽库中其余成员
import 'package:lib1/lib1.dart' show foo;
// 屏蔽foo,库中其余成员均可见
import 'package:lib2/lib2.dart' hide foo;
复制代码
为了减小 APP 的启动时间,加载不多使用的功能,咱们还能够延迟导入库。使用 deferred as
关键字延迟导入
import 'package:deferred/hello.dart' deferred as hello;
// 当须要使用时,再经过库标识符调用 loadLibrary函数加载
hello.loadLibrary();
复制代码
Dart与JavaScript同样,是一个单线程模型。但这并不意味着Dart中不能进行异步编程,只是这种异步编程区别于传统的多线程异步方式。
Dart中的全部代码都只在一个线程上运行,但Dart代码能够运行在多个isolate上。isolate能够看作一个微小的线程,isolate由虚拟机调度,isolate之间没有共享内存,所以它们之间没有竞争,不须要锁,不用担忧死锁,所以开销小,性能高。因为没有共享内存,因此它们之间惟一的通讯只能经过Port进行,并且Dart中的消息传递也老是异步的。
Dart中两种方式可使用Future
对象来进行异步编程
async
和 await
关键字使用async
和await
编写代码很是简单,并且编写的代码看起来有点像同步代码,其实是异步的。
// 导入io库,调用sleep函数
import 'dart:io';
// 模拟耗时操做,调用sleep函数睡眠2秒
doTask() async{
await sleep(const Duration(seconds:2));
return "Ok";
}
// 定义一个函数用于包装
test() async {
var r = await doTask();
print(r);
}
void main(){
print("main start");
test();
print("main end");
}
复制代码
运行结果:
main start
main end
Ok
复制代码
在函数签名中加入async
关键字,表示该函数异步执行,await
表示等待异步结果执行完成返回Future
对象。但有一点须要注意,await
只能在async
函数中出现,所以每每须要再定义一个async
函数,用于包装。上述代码中test
函数就是用于包装。
关于Dart异步编程的更多详细知识,请跳转本人另外一篇博客 Dart 异步编程详解之一文全懂
以上是本篇的所有内容,关于博主的更多技术文章,请跳转到如下连接,谢谢!
GitHub