上手指南 | Dart,随用随查

简介: 上手指南 | Dart,随用随查

最近打算要入坑 Flutter,所以在此进行记录,随用随查;


不要怂,就是干,


一个简单的 Dart 程序


//🐷函数,应用从这里开始执行
main(){
  var number = "Hello World";
  printInteger(number);
}
//定义一个函数
printInteger(int aNumber){
  print('The number is $aNumber');
}


重要的概念


在学习 Dart 语言时,应该基于以下事实和概念


任何保存在变量中的都是一个对象;所有的对象都对应一个类的实例,函数 和 null 都是对象,所有对象基于 Object 类

虽然 Dart 是强类型的,但是 Dart 可以进行类型推断,如上面代码变量 number 被推断为 int 类型;如果要明确说明不需要任何类型, 需要使用特殊类型 dynamic

Dart 支持泛型,如 List , List(任何类型的对象列表)

Dart 支持顶级函数 main() ,同样函数绑定在类或对象上(分别是 静态函数 和 实例函数 )。 以及支持函数内创建函数 ( 嵌套 或 局部函数 ) 。

Dart 支持顶级变量

dart 没有关键字 public ,protected 和 private,如果以 _ 开头,则相对于库是私有的

三目运算符:条件 condition ? Expr1 : expr2

类型问题:警告和错误,警告表示代码可能无法正常工作,但不会阻挡程序的执行,错误可能是编译或者运行时的错误,编译时错误会阻止代码的执行,运行时错误会导致代码在执行中引发异常(#exception)


关键字


image.png

应该避免这些单词作为标识符


带有 1 的单词为 上下文关键字,仅在特定位置具有含义,他们在任何地方都是有效标识符

带有 2 的为 内置标识符,这些关键字大多数地方都是有效的标识符,不能用于类型名称 和 import 前缀

带有 3 的是 Dart 1.0 发布后添加的异步支持相关的更新,作为限制类保留字。


变量


var name = "345"; //创建一个变量并初始化
dynamic name = "345"; // name 被推断为 String类型
String name = "345";//显式声明


dynamic:该类型具有所有可能的属性和方法,一个变量被 dynamic 修饰,相当于告诉系统,我知道这个类型到底是什么。使用后再编译时不会推断数据的类型,但是运行时会推断。


默认值


未初始化的变量默认值是 null,即使是数字类型也是 null。Dart 中一切皆是对象


Final 和 Const


使用过程中从来都不会被修改的变量,可用 final 或者 const。final 变量的值只能被设置一次,const 变量在编译时就已经固定。


内建类型


Number:有两种类型1,int,整数值不大于 64位;double 双精度浮点数


String::Dart 字符串是一组 UTF-16 单元序列,字符串通过单引号 或者 双引号创建


可使用 + 将字符串连接为一个;使用三个或三个双引号可实现多行字符串对象的创建


使用 r"" 前缀,可以创建“原始 raw 字符串”


Boolean: true and false


List:(也被称为 Array)


var list = [1, 2, 3];
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);


在 list 之前添加 const 关键字,可定义 List 类型的编译时常量


Map:用来关联 key 和 value,同一个 map 中 key 只能出现一次


var constantList = const [1, 2, 3];
var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};


Set:set 是一个元素唯一的集合


var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
var names = <String>{};
// Set<String> names = {}; // 这样也是可以的。
// var names = {}; // 这样会创建一个 Map ,而不是 Set 。
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';


Rune: (用于在字符串中表示 Unicode 字符)


在 Dart 中, Rune 用来表示字符串中的 UTF-32 编码字符


表示 Unicode 编码的常用方法是, \uXXXX, 这里 XXXX 是一个4位的16进制数。 例如,心形符号 (♥) 是 \u2665。 对于特殊的非 4 个数值的情况, 把编码值放到大括号中即可。 例如,emoji 的笑脸 (�) 是 \u{1f600}。


0a2653c851af460fa595bd959398a8f1.png


Symbol


Symbol 对象表示 Dart 程序中声明的运算符或者标识符,你一般不会使用到他


函数


Dart 是一门真正的面对对象语言,甚至其中的函数也是对象,并且有他的类型 Function。意味着函数可以被赋值给变量,或者作为参数传递给其他函数,也可以把 Dart 类的实例当做方法来调用


//省略类型声明,函数可以正常使用
isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
//如果只有一句话,可简洁写法
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;


=> *expr* 语法是 { return *expr*; } 的简写。 => 符号 有时也被称为 箭头 语法 ,箭头后面只能是一个表达式;


调用时可选参数


abc(bold: true, hidden: false);


可指定具体的参数值


const Scrollbar({Key key, @required Widget child})


使用 @required 表示参数是 required 性质的命名参数。


位置可选参数


String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}


将参数放在 [] 中,来标记参数是可选的。表示该参数可以不传


默认参数值


// bold 值为 true; hidden 值为 false.
void abc(bool bold = false);


void doStuff(
    {List<int> list = const [1, 2, 3],
    Map<String, String> gifts = const {
      'first': 'paper',
      'second': 'cotton',
      'third': 'leather'
    }}) {
}


接受一个 list 和 map,并指定参数的默认值


main() 函数


void main(){
}
// 这样运行应用: dart args.dart 1 test
void main(List<String> arguments) {
  print(arguments);
}


main 函数返回值为 空,参数为一个可选的 List


匿名函数


多数函数是有名字的,比如 main() 等,dart 可以创建没有名字的函数,这种函数被称为匿名函数,**有时候也被称为 lambda 或者 closure。**匿名函数可以赋值到一个变量中,例如:在一个集合中可以添加或者删除一个匿名函数


main(){
  var list = [];
  list.add(1);
  list.add(2);
  list.add(3);
  list.add(4);
  list.forEach((num){
    print('位置:${list.indexOf(num)} ;值:$num');
  });
}


上面定义了一个 无类型参数num 的匿名函数,list 遍历时,每次都会调用这个函数,并将值传递给到匿名函数中。


如果只有一句话,可使用如下写法:


list.forEach((num)=>print('位置:${list.indexOf(num)} ;值:$num'));


函数的赋值与传递


main(){
  //将匿名函数赋值给变量
  var one = (num)=>print(' 值:$num');
  one(10);
  //将普通函数赋值给变量
  var two = abc;
  two(20);
  //将匿名函数传递给普通函数
  abc2((str) => print("abc $str"));
}
void abc2(fun(String str)){
 fun("输出-------》");
}
void abc(num){
  print("哈哈哈:$num");
}


词法作用域


dart 是一门词法作用域的编程语言。


简单的说变量的作用域在编写代码的时候就已经确定了,花括号内就是变量的可见作用域


bool topLevel = true;
void main() {
  var insideMain = true;
  void myFunction() {
    var insideFunction = true;
    void nestedFunction() {
      var insideNestedFunction = true;
      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}


内部可以访问所有的变量,一直到顶级作用域内的变量。


词法闭包


闭包即一个函数对象。即使函数的调用在他原始的作用域之外,依然能访问他在词法作用域内的变量


/// 返回一个函数,返回的函数参数与 [addBy] 相加。
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}
void main() {
  // 创建一个加 2 的函数。
  var add2 = makeAdder(2);
  // 创建一个加 4 的函数。
  var add4 = makeAdder(4);
  assert(add2(3) == 5);
  assert(add4(3) == 7);
}


测试函数是否相等


void foo() {} // 顶级函数
class A {
  static void bar() {} // 静态方法
  void baz() {} // 示例方法
}
void main() {
  var x;
  // 比较顶级函数。
  x = foo;
  assert(foo == x);
  // 比较静态方法。
  x = A.bar;
  assert(A.bar == x);
  // 比较实例方法。
  var v = A(); // A的1号实例
  var w = A(); // A的2号实例
  var y = w;
  x = w.baz;
  // 两个闭包引用的同一实例(2号),
  // 所以它们相等。
  assert(y.baz == x);
  // 两个闭包引用的非同一个实例,
  // 所以它们不相等。
  assert(v.baz != w.baz);
}


返回值


所有函数都会有返回值,如果没有明确返回值,函数体会被隐式的添加 return null;语句


运算符


Dart 定义的运算符如下:

image.png

上表中,多数运算符可被重载


条件表达式


*condition* ? *expr1* : *expr2*


如果条件为 true, 执行 expr1 (并返回它的值): 否则, 执行并返回 expr2 的值。


*expr1* ?? *expr2*


如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。


级联运算符


级联运算符可以对一个对象进行一些了操作,除了调用函数,还可以访问同一对象上的字段属性,


void main() {
  new A()
   ..a1()
   ..a2();
}
class A{
  void a1(){
  print('a1');
  }
  void a2(){
  print('a2');
  }
}
//a1  a2


级联运算符可进行嵌套


final addressBook = (AddressBookBuilder()
      ..name = 'jenny'
      ..email = 'jenny@example.com'
      ..phone = (PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();


控制流程语句


if and else
for loops
for (var i = 0; i < 5; i++) {
  message.write('!');
}


也可使用 forEach,或者 for-in


candidates.forEach((candidate) => candidate.interview());
var collection = [0, 1, 2];
for (var x in collection) {
  print(x); // 0 1 2
}


while and do-while loops


break and continue


switch and case


和 java 基本类似,可以比较整数,字符串,或者编译时常量,比较的对象都是同一个实例(并且不能是子类),枚举也可以使用 switch 语句


assert


如果 assert 中的布尔条件为 false,那么正常的程序执行流程会被中断


assert 语句只在开发环境中有效,在生产环境是无效的


异常


Dart 可以抛出和捕获异常,如果没有被捕获,则会抛出,最终导致程序终止运行


和 Java 不同,Dart 中的所有异常时非检查异常,方法不会声明它们抛出的异常,也不要求捕获任何异常


Dart 提供了 Exception 和 Error 类型,以及一些子类型。也可以自定义异常类型。此外,Dart 程序可以抛出任何 非null 对象,不仅限 Exception 和 Error 对象。


throw


throw FormatException('Expected at least 1 section');


抛出任意的对象


throw 'Out of llamas!';


在使用表达式的地方抛出异常


void distanceTo(Point other) => throw UnimplementedError();


Catch


捕获异常


try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 一个特殊的异常
  buyMoreLlamas();
} on Exception catch (e) {
  // 其他任何异常
  print('Unknown exception: $e');
} catch (e) {
  // 没有指定的类型,处理所有异常
  print('Something really unknown: $e');
}


catch 函数可以指定 1到2个参数,第一个为异常对象,第二个为堆栈信息(StackTrace对象)


try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}


如果部分异常需要处理,可使用 rethrow 将异常重新抛出


void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // Runtime error
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // Allow callers to see the exception.
  }
}
void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}


finally


无论是否 try 住异常,finally 都会执行。如果 try 住异常,会先执行对应的 catch,最后执行 finally



Dart 是一种基于类和 mixin 继承机制的面向对象的语言,每个对象都是一个类的实例,所有的类都继承于 Object. 。 基于 * Mixin 继承* 意味着每个类(除 Object 外) 都只有一个超类, 一个类中的代码可以在其他多个继承类中重复使用。


创建对象


var p = Point(2, 2);


// 为实例的变量 y 设置值。
p.y = 3;
// 获取变量 y 的值。
assert(p.y == 3);
//如果 p 非空,则设置y=8
p?.y = 8
// 调用 p 的 distanceTo() 方法。
num distance = p.distanceTo(Point(4, 4));


使用 ?. 来代替 . , 可以避免因为左边对象可能为 null , 导致的异常


常量构造函数


var p = const ImmutablePoint(2, 2);


在构造函数名之前加 const 关机字,来创建编译时常量


注意:构造两个相同编译时常量会产生一个相同的实例


在常量上下文中,const 可以被省略:


// 这里有很多的 const 关键字。
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};


// 仅有一个 const ,由该 const 建立常量上下文。
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};


需要在 Dart2中,一个常量上下文中的 const 关键字可以被省略


获取对象类型


使用对象的 runtimeType 属性, 可以在运行时获取对象的类型, runtimeType 属性回返回一个 Type 对象。


实例变量

class Point {
  num x; // 声明示例变量 x,初始值为 null 。
  num y; // 声明示例变量 y,初始值为 null 。
  num z = 0; // 声明示例变量 z,初始值为 0 。
}


未初始化的变量为 null


所有实例变量都隐式生成 getter 方法,非 final 的变量会生成 setter 方法


默认构造


没有声明构造时,Dart 会提供一个默认的构造


构造函数不被继承


子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数) 。


命名构造函数


使用命名构造函数可以为一个类实现多个构造函数,也可以使用命名构造函数来更清晰的表明函数意图:


class Point {
  num x, y;
  Point(this.x, this.y);
  // 命名构造函数
  Point.origin() {
    x = 0;
    y = 0;
  }
}


切记,构造函数不能够被继承, 这意味着父类的命名构造函数不会被子类继承。 如果希望使用父类中定义的命名构造函数创建子类, 就必须在子类中实现该构造函数。


调用父类field默认构造函数


执行顺序如下:


initializer list (初始化参数列表)
superclass’s no-arg constructor (父类的无名构造函数)
main class’s no-arg constructor (主类的无名构造函数)
class Person {
  String firstName;
  Person.fromJson(Map data) {
    print('in Person');
  }
}
class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}
main() {
  var emp = new Employee.fromJson({});
  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}


常量构造函数


class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);
  final num x, y;
  const ImmutablePoint(this.x, this.y);
}


工厂构造函数


class Logger {
  final String name;
  bool mute = false;
  // 从命名的 _ 可以知,
  // _cache 是私有属性。
  static final Map<String, Logger> _cache =
      <String, Logger>{};
  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }
  Logger._internal(this.name);
  void log(String msg) {
    if (!mute) print(msg);
  }
}


其实就是一个工厂模式,传如对于的 name,然后获取到对应的实例


关于其他的


抽象类,枚举,这些就不详细的说了,都是基本操作,和java差不多。如果不懂,可自行到官网查看


本文参考自:官方文档


相关文章
|
4月前
|
Dart 编译器 API
Dart笔记:Dart 库
Dart笔记:Dart 库
116 0
|
9月前
|
Dart
Flutter 入门指南之 Dart 语言基础介绍
Dart是一种由Google开发的通用编程语言,用于构建跨平台的移动、Web和桌面应用程序。以下是Flutter入门指南中的Dart语言基础知识:
|
Dart Java 编译器
手把手教你写 Dart ffi
本文以step by step的方式说明了Dart ffi的使用,适合新手学习。
手把手教你写 Dart ffi
|
10月前
|
Dart Linux 开发工具
《深入浅出Dart》搭建环境
搭建环境 对于任何编程语言来说,搭建一个有效且稳定的开发环境是编程旅程的第一步。对于Dart,这个过程已经变得非常简单。下面是一篇关于如何安装和配置Dart环境的详细指南: 第一步:下载Dart SDK 首先,你需要下载Dart的软件开发包(SDK)。SDK包含了运行和开发Dart应用所需要的一切工具,包括Dart VM,Dart的包管理器Pub,以及一系列用于编译和调试的工具。你可以从Dart的官方网站下载最新版本的Dart SDK。
100 0
|
10月前
|
Dart 测试技术 JavaScript
《深入浅出Dart》Dart测试
单元测试和集成测试 Dart的生态系统提供了一个完善的测试框架来进行代码的单元测试和集成测试。以下是一些基本的测试知识。 Dart单元测试 单元测试是在软件开发中进行的最小单元的测试。在Dart中,我们可以使用内置的test包来进行单元测试。 安装测试包 首先,我们需要在pubspec.yaml中添加test的依赖:
105 0
|
10月前
|
Dart JavaScript 前端开发
《深入浅出Dart》Dart模块化
Dart模块化详解 在大型软件项目中,模块化是必不可少的,它可以帮助我们更好地组织和管理代码,提高代码的可读性和可维护性。在Dart中,模块化是通过库(libraries)来实现的。 库的定义与使用
85 0
|
10月前
|
Dart Linux 开发工具
《深入浅出Dart》Flutter环境的安装与配置
Flutter环境的安装与配置 在开发Flutter应用之前,我们首先需要安装和配置Flutter环境。在本文中,我们将分别介绍Windows,macOS和Linux下的安装和配置过程。首先,需要满足以下基本要求: 操作系统:Windows 7 SP1或更高版本,macOS 10.10或更高版本,或Linux(对各发行版没有特殊要求) 磁盘空间:1.64 GB以上 Git:确保您的操作系统上安装了Git。
112 0
|
Rust 前端开发 安全
通过跨端程序tauri,来简单入门一下rust
Tauri 是一个跨平台 GUI 框架,与 Electron 的思想基本类似。Tauri 的前端实现也是基于 Web 系列语言,Tauri 的后端使用 Rust。Tauri 可以创建体积更小、运行更快、更加安全的跨平台桌面应用。
1169 0
Dart语言笔记
在赋值运算里,如果++ --写在前面,这时先运算,再赋值,如果++ --在后面,先赋值,再进行运算
|
移动开发 Dart 前端开发
《Flutter开发从入门到实战》:为什么要学Flutter?
《Flutter开发从入门到实战》:为什么要学Flutter?
178 1
《Flutter开发从入门到实战》:为什么要学Flutter?