Dart语言——45分钟快速入门(下)

栏目: IOS · 发布时间: 5年前

内容简介:Dart中的类与Java中的相似,不同的是,Dart中没有以上代码,在Dart中还有一种简化写法,可以自动在构造方法中对成员变量初始化。另外还需要注意一点,Dart中没有构造方法的重载,不能写两个同名的构造方法。
// Dart中定义一个类
class Person {
  String name;
  int age;

  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
}
复制代码

Dart中的类与 Java 中的相似,不同的是,Dart中没有 privatepublic 这些成员访问修饰符。如果是类私有的成员,不希望外面访问,只需要在成员变量之前加上一个下划线 _ 变为私有即可。

以上代码,在Dart中还有一种简化写法,可以自动在构造方法中对成员变量初始化。

// Dart中定义一个类
class  Person {
    String name;
    int age;

    // 在构造方法中初始化成员变量时,可使用如下写法简化
    Person(this.name, this.age);

    // 如需处理其他变量时,也可单独对其操作
    // Person(this.name, this.age, String address){
    //     print(address);
    // }
    // 注意,构造方法不能重载,以上注释掉
}
复制代码

另外还需要注意一点,Dart中没有构造方法的重载,不能写两个同名的构造方法。

Getters 和 Setters方法

在Java中,一般不会直接在类的外部去访问类成员,通常使用setter和getter方法来操作类的成员变量。而在Dart语言中,所有类中都包含隐式的getter方法,对于非 final 修饰的成员,类中还包含隐式的setter方法。这就意味着,在Dart中,你可以直接在类外部通过 . 操作符访问类成员。这一特点使得Dart语法更加简洁,不会写出满屏的setXXX、getXXX方法。

当然,很多时候我们调用setter和getter方法并不仅仅是为了赋值和访问,而是为了一些额外的处理,这时候我们只需要使用 setget 关键字实现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 会更友好。

构造方法

如果没有定义构造方法,则会有一个默认的无参构造方法,并且会调用超类的无参构造方法。

命名构造方法

上面已经说过,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);
}
复制代码
Dart语言——45分钟快速入门(下)
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(); 
复制代码

使用 showhide 关键字控制库中成员的可见性

// 仅导入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 对象来进行异步编程

  • 使用 asyncawait 关键字
  • 使用 Future API

使用 asyncawait 编写代码非常简单,而且编写的代码看起来有点像同步代码,实际上是异步的。

// 导入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

Dart语言——45分钟快速入门


以上所述就是小编给大家介绍的《Dart语言——45分钟快速入门(下)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

群智能算法及其应用

群智能算法及其应用

高尚 / 中国水利水电出版社 / 2006-5 / 25.00元

《群智能算法及其应用》系统地描述了蚁群算法和粒子群优化算法的理论和实现技术及其应用,简单地介绍了鱼群算法。《群智能算法及其应用》着重强调各种算法的混合,讨论了蚁群算法与模拟退火算法的混合、蚁群算法与遗传算法的混合、蚁群算法与混沌理论混合、模拟退火算法、遗传算法与粒子群优化算法混合、混沌理论与粒子群优化算法的混合以及蚁群算法与粒子群优化算法的混合。书中还讨论了群智能算法在旅行商问题、武器一目标分配问......一起来看看 《群智能算法及其应用》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试