动态

详情 返回 返回

Dart學習筆記:語法 - 动态 详情

本文更新於2024-12-22,使用Dart 2.18.2。

目錄
  • 關鍵字
  • 常量
  • 變量
  • 基本數據類型
    • 數值
    • 字符串
    • 布爾
    • 列表
    • 集合
    • 映射
  • 運算符
    • 運算符優先級
    • 算數運算符
    • 關係運算符
    • 類型判定運算符
    • 賦值運算符
    • 邏輯運算符
    • 位運算符
    • 條件運算符
    • 訪問運算符
  • 流程控制
    • 條件語句
      • if-else
      • switch-case
    • 循環語句
      • for
      • for-in
      • while
      • do-while
    • break語句
    • continue語句
  • 斷言
  • 異常
  • 函數
    • 箭頭函數
    • 可選位置參數
    • 可選命名參數
    • 閉包
    • 主函數
    • 成員變量/實例變量
      • getter和setter
    • 靜態變量/類變量
    • 構造函數
      • 默認無參構造函數
      • 顯式聲明構造函數
      • 命名構造函數
      • 構造函數簡寫
      • 初始化列表
      • 重定向構造函數
      • 常量構造函數
      • 工廠方法的構造函數
      • 自動調用父類無參構造函數
      • 顯式調用父類構造函數
    • 成員方法/實例方法
    • 靜態方法/類方法
    • 繼承
      • 函數重寫
      • 運算符重寫
      • 抽象類與抽象方法
    • 接口
    • Mixin特性
    • 可調用的類
  • 枚舉
  • 類型定義
  • 泛型
    • 函數泛型
    • 類泛型
  • 異步
    • 在循環中異步
  • 註解/元數據
    • @deprecated
    • @override
    • @proxy
  • 註釋
    • 單行註釋
    • 多行註釋
    • 文檔註釋
    • import內置庫
    • import包庫
    • import本地庫
    • import-as
    • import-show
    • import-hide
    • import-deferred as懶加載

可以使用dart run FILENAME運行程序文件。

關鍵字

  • abstract
  • as
  • assert
  • async
  • await
  • break
  • case
  • catch
  • class
  • const
  • continue
  • covariant
  • default
  • deferred
  • do
  • dynamic
  • else
  • enum
  • export
  • extends
  • external
  • factory
  • false
  • final
  • finally
  • for
  • get
  • hide
  • if
  • implements
  • import
  • in
  • interface
  • is
  • library
  • mixin
  • new
  • null
  • on
  • operator
  • part
  • rethrow
  • return
  • set
  • show
  • static
  • super
  • switch
  • sync
  • this
  • throw
  • true
  • try
  • typedef
  • var
  • void
  • while
  • with
  • yield

常量

const聲明的是編譯時常量。

cosnt s1 = "";
const String s2 = "";

final s3 = "";
final String s4 = "";

var list = const[1, 2, 3];
const list = [1, 2, 3];

var dog = const Dog();
const dog = Dog();

變量

var a1;
var a2 = null;
dynamic a3;
dynamic a4 = "";

var s1 = "";
String s2 = "";

基本數據類型

數值

  • int: 64位。範圍為[-2^63 ~ 263-1]。編譯為JavaScript時使用JavaScript的範圍[-253 ~ 2^53-1]。
  • double:64位。範圍約為[-1.7E308 ~ 1.7E308]。

字符串

使用UTF-16編碼。

var s1 = '\'';
var s2 = "\"";

var s3 = '''1
2''';
var s4 = """1
2""";

var s5 = "\u2665\u{1f47b}";

var a1 = '$s1 ${s2}';
var a2 = "$s1 ${s2}";
var a3 = s1 + " " + s2;
var a4 = s1 * 3;
var a5 = "${s1+s2}";

布爾

var b1 = true;
bool b2 = false;

列表

var l = [1, "2", 1];

集合

var s = {1, "2"};

映射

var m1 = {};
var m2 = {
	"a": 1,
	"b": "2"
};

運算符

運算符優先級

從高到低依次為:

描述 運算符
一元后綴 ++,--,(),[],.,?.
一元前綴 -,!,~,++,--
乘除 *,/,~/,%
加減 +,-
移位 <<,>>,>>>
按位與 &
按位異或 ^
按位或 |
關係和類型測試 >=,>,<=,<,as,is,is!
相等判斷 ==,!=
邏輯與 &&
邏輯或 ||
為空判斷 ??
條件 ? :
級聯 ..
賦值 =,+=,-=,*=,/=,~/=,%=,<<=,>>=,>>>=,&=,^=,|=

算數運算符

運算符 用法 描述
+ 1 + 2 相加
- 1 - 2 相減
- -1 負數
* 1 * 2 相乘
/ 1 / 2 相除(返回浮點數)
~/ 1 ~/ 2 相除(返回整數)
% 1 % 2 取餘
++ ++n (前)自增
++ n++ (後)自增
-- --n (前)自減
-- n-- (後)自減

關係運算符

運算符 用法 描述
== 1 == 2 相等
!= 1 != 2 不等
> 1 > 2 大於
>= 1 >= 2 大於等於
< 1 < 2 小於
<= 1 <= 2 小於等於

類型判定運算符

運算符 用法 描述
as 1 as int 類型轉換(結果為運算符後的類型)
is 1 is int 是此類型(結果為bool類型)
is! 1 is! int 非此類型(結果為bool類型)

賦值運算符

運算符 用法 描述
= n = 2 賦值
+= n += 2 即 n = n + 2
-= n -= 2 即 n = n - 2
*= n *= 2 即 n = n * 2
/= n /= 2 即 n = n / 2
~/= n ~/= 2 即 n = n ~/ 2
%= n %= 2 即 n = n % 2
<<= n <<= 2 即 n = n << 2
>>= n >>= 2 即 n = n >> 2
>>>= n >>>= 2 即 n = n >>> 2
&= n &= 2 即 n = n & 2
|= n |= 2 即 n = n | 2
^= n ^= 2 即 n = n ^ 2

邏輯運算符

運算符 用法 描述
! !true
|| true || false
&& true && false

位運算符

運算符 用法 描述
& 1 & 2 按位與
| 1 | 2 按位或
^ 1 ^ 2 按位異或
~ ~1 按位取反(結果為相反數減一)
<< 1 << 2 按位左移
>> 1 >> 2 有符號按位右移(左側填充符號位)
>>> 1 >>> 2 無符號按位右移(左側填充0)

條件運算符

運算符 用法 描述
? : v ? t : f 條件判斷(如v為true取值t,否則取值f)
?? v ?? n 非空判斷(如v非null取值v,否則取值n)

訪問運算符

運算符 用法 描述
() f() 函數調用
[] a[1] 使用索引訪問元素
. a.b 訪問對象成員
?. a?.b 條件訪問對象成員(如a非null取值b,否則取值null)
.. v..f1()..f2() 級聯運算(等價於v.f1();v.f2(),嚴格意義上並不是一個運算符,只是一個特殊語法)

流程控制

條件語句

if-else

if (condition1) {
} else if (condition2) {
} else {
}

switch-case

switch (v) {
	case 1:
	case 2:
		print("");
		break;
	default:
}

循環語句

for

for (var i = 0; i < n; i++) {
}

for-in

for (var v in set) {
}

while

while (condition) {
}

do-while

do {
} while(condition);

break語句

switch (v) {
	case 1:
	case 2:
		print("");
		break;
	default:
}

for (var i = 0; i < n; i++) {
	break;
	print(i);
}

continue語句

for (var i = 0; i < n; i++) {
	if (i == 0) {
		continue;
	}
	print(i);
}

斷言

斷言只在開發(Checked)模式下有效,在生產(Production)模式下無效。

assert(flag);

異常

try {
	throw new Exception();
} on RangeError {
	rethrow;
} catch (e) {
} finally {
}

函數

String join(String a, String b) {
	return a + b;
}

add(a, b) {
	return a + b;
}

run() {
}
var s = join("a", "b");
var n = add(1, 2);
var a = run();

箭頭函數

String join(String a, String b) => a + b;

可選位置參數

String join(String a, String b, [String c = "", String d = ""]) {
	return a + b + c + d;
}
var s = join("a", "b", "c");

可選命名參數

String join(String a, String b, {String c: "", d: ""}) {
	return a + b + c + d;
}
var s = join("a", "b", c: "c");

閉包

Function hello(String name) {
	var say = () {
		print("Hello $name");
	};
	return say;
}
var say = hello("Tom");
say();

主函數

void main(List<String> args) {
}

成員變量/實例變量

class Person {
	String name = "";
	int age = 0;
}

getter和setter

會為每個成員變量自動生成getter方法,對於非final修飾的成員變量也會自動生成setter方法。

class Person {
	String name = "";
	
	String get Name {
		return name;
	}

	set Name(String n) {
		name = n;
	}
}
var p = new Person();
p.Name = "Tom";
print(p.Name);

靜態變量/類變量

class Person {
	String name = "";
	int age = 0;

	static int total = 1000;
	static Person me = new Person();
}
print(Person.total);

構造函數

構造函數的執行順序為:實例變量賦值 -> 初始化參數列表 -> 父類構造函數 -> 本類構造函數。

默認無參構造函數

class Person {
	String name = "";
	int age = 0;
}
var p1 = new Person();
var p2 = Person();

默認自動生成無參構造函數:

	Person() {
	}

顯式聲明構造函數

class Person {
	String name = "";
	int age = 0;
	
	Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
}
var p = new Person("Tom", 10);

命名構造函數

class Person {
	String name = "";
	int age = 0;
	
	Person.myself(age) {
		name = "Tom";
		this.age = age;
	}
}
var p = new Person.myself(10);

構造函數簡寫

class Person {
	String name = "";
	int age = 0;
	
	Person(this.name, this.age);
	
	Person.create(this.name, {this.age: 0});
}

class Student extends Person {
	String number = "";

	Student(super.name, super.age);
}
var p1 = new Person("Tom", 10);
var p2 = new Person.create("Tom", age: 10);

var s = new Student("Tom", 10);

初始化列表

class Person {
	String name = "";
	int age = 0;
	
	Person.myself(int age): name = "Tom", this.age = age {
	}
}
var p = new Person.myself(10);

重定向構造函數

class Person {
	String name = "";
	int age = 0;
	
	Person(this.name, this.age);
	
	Person.myself(int age): this("Tom", age);
}
var p = new Person.myself(10);

常量構造函數

class Person {
	final String name;
	final int age;
	
	const Person(this.name, this.age);
}
var p1 = new Person("Tom", 10);
var p2 = const Person("Tom", 10);

工廠方法的構造函數

class Person {
	String name = "";
	int age = 0;
	
	static Map<String, Person> _people = {};
	
	Person(this.name, this.age);
	
	factory Person.Tom() {
		var name = "Tom";
		var p = _people[name];
		if (p == null) {
			p = Person(name, 0);
			_people[name] = p;
		}
		return p;
	}
}
var p = new Person.Tom();

自動調用父類無參構造函數

class Person {
	String name = "";
	int age = 0;
}

class Student extends Person {
	String number = "";
}
var s = new Student();

顯式調用父類構造函數

class Person {
	String name = "";
	int age = 0;
	
	Person(this.name, age);
	
	Person.myself(int age) {
		name = "Tom";
		this.age = age;
	}
}

class Student extends Person {
	String number = "";

	Student(String name, int age, String number): super(name, age) {
		this.number = number;
	}

	Student.myself(int age, String number): this.number = number, super.myself(age) {
	}
}
var s1 = new Student("Tom", 10, "no.1");
var s2 = new Student.myself(10);

成員方法/實例方法

class Person {
	String name = "";
	int age = 0;

	String info() {
		return "Person name is $name and age is $age.";
	}
}
var s = new Student();
s.info();

靜態方法/類方法

class Person {
	String name = "";
	int age = 0;

	static readme() {
		print("Person!");
	}
}
Person.readme();

繼承

不支持多繼承。

class Person {
	String name = "";
	int age = 0;
	
	String info() {
		return "Person name is $name and age is $age.";
	}
}

class Student extends Person {
	String number = "";
}
var s = new Student();
s.info();

函數重寫

class Person {
	String name = "";
	int age = 0;
	
	String info() {
		return "Person name is $name and age is $age.";
	}
}

class Student extends Person {
	String number = "";
	
	@override
	String info() {
		return super.info() + " Student number is $number.";
	}
}

運算符重寫

class Person {
	String name = "";
	int age = 0;
	
	Person(this.name, this.age);
		
	Person operator +(Person p) {
		var name = this.name + " and " + p.name;
		var age = this.age + p.age;
		return new Person(name, age);
	}
}
var p1 = new Person("Tom", 10);
var p2 = new Person("Jerry", 9);
var p = p1 + p2;

可重寫的運算符有:

  • <
  • <=
  • =

  • ==
  • /
  • ~/
  • %
  • &
  • |
  • ^
  • ~
  • <<
  • []
  • []=

抽象類與抽象方法

抽象類無法被實例化。

abstract class Person {
	String name = "";
	int age = 0;
	
	String info();
}

class Student extends Person {
	String number = "";
	
	@override
	String info() {
		return "Person name is $name and age is $age. Student number is $number.";
	}
}

接口

class Person {
	String name = "";
	int age = 0;
}

abstract class Say {
	int voice = 0;

	void say();
}

class Hello {
	void hello() {
		print("hello!");
	}
}

class Student extends Person implements Say, Hello {
	String number = "";

	@override
	int voice = 0;

	@override
	void say() {
		print("Person name is $name and age is $age. Student number is $number.");
	}

	@override
	void hello() {
		print("hello!");
		say();
	}
}

Mixin特性

class Person {
	String name = "";
	int age = 0;
}

class Run {
	void run() {
		print("run!");
	}
}

abstract class Say {
	void say();
}

class Student extends Person with Run implements Say {
	String number = "";

	@override
	void say() {
		print("Person name is $name and age is $age. Student number is $number.");
	}
}
var s = new Student();
s.run();

可調用的類

class Run {
	call() {
		print("run");
	}
}

class Say {
	call(String a, String b) {
		print("say $a $b");
	}
}
var run = new Run();
run();

var say = new Say();
say("a", "b");

枚舉

無法繼承,無法使用Mixin特性,無法實例化。

enum Grade {
	grade1,
	grade2
}
var grade = Grade.grade1;
var index = Grade.grade1.index;

類型定義

typedef Repeat = String Function(String str);
typedef Name = String;
Name name = "Tom";
Repeat f = (str) {
  return str + ", " + str;
};
var s = f(name);

泛型

函數泛型

String add<T>(T a, T b) {
	return a.toString() + b.toString();
}

String addString<T extends String>(T a, T b) {
	return a + b;
}
add(1, 2);
addString("a", "b");

類泛型

class Add<T> {
	String add(T a, T b) {
		return a.toString() + b.toString();
	}
}

class AddString<T extends String> {
	String add(T a, T b) {
		return a + b;
	}
}
new Add().add(1, 2);
new AddString().add("a", "b");

異步

異步本質上是使用isolates運行模式進行併發。

void main(List<String> args) {
	work();
	print(2);
}

work() async {
	print(1);
	var str = await takeTime();
	print(4);
	print(str);
}

Future<String> takeTime() async {
	var str = await new Future.delayed(new Duration(seconds: 2), () {
		print("...");
		print(3);
		return "hello";
	});
	return str;
}

在循環中異步

void main(List<String> args) async {
	Stream<String> stream = Stream.fromFuture(new Future.delayed(new Duration(seconds: 2), () {
		print("...");
		print(2);
		return "hello";
	}));
	print(1);
	await for (var str in stream) {
			print(str);
	}
	print(3);
}

註解/元數據

@deprecated

棄用。

@deprecated
// Should use Hello();
void hello() {
}

@override

重寫。

class Person {
	String name = "";
}

class Student extends Person {
	@override
	String name = "";
}

@proxy

註釋

單行註釋

// Comment.

多行註釋

/*
Comment.
Comment.
Comment.
*/

/* Comment.
Comment.
Comment. */

文檔註釋

/**
 * This is a demo.
 * 
 * Refer [say] for detail.
 */
void hello() {
}

/// This is a demo.
/// Used by [hello].
void say() {
}

標識符除非以“_”開頭,否則都是對庫外可見的。

import內置庫

import 'dart:math';

void main(List<String> args) {
  print(pi);
}

import包庫

import 'package:flutter/material.dart';

import本地庫

lib.dart:

var _name = "lib.dart";

class Hello {
	void hello() {
		print("hello " + _name);
	}
}

main.dart:

import 'lib.dart';

void main(List<String> args) {
	new Hello().hello();
}

import-as

src/liba.dart:

class Hello {
	void helloA() {
		print("hello a");
	}
}

src/libb.dart:

class Hello {
	void helloB() {
		print("hello b");
	}
}

main.dart:

import 'src/liba.dart' as liba;
import 'src/libb.dart' as libb;

void main(List<String> args) {
	new liba.Hello().helloA();
	new libb.Hello().helloB();
}

import-show

lib.dart:

class Hello {
}

class Say {
}

class Run {
}

main.dart:

import 'lib.dart' show Hello, Say;

void main(List<String> args) {
	new Hello();
	new Say();
}

import-hide

lib.dart:

class Hello {
}

class Say {
}

class Run {
}

main.dart:

import 'lib.dart' hide Run;

void main(List<String> args) {
	new Hello();
	new Say();
}

import-deferred as懶加載

lib.dart:

class Hello {
	hello() {
		print("hello");
	}
}

main.dart:

import 'lib.dart' deferred as lib;

void main(List<String> args) {
	print("main");
	hello();
}

void hello() async {
	await lib.loadLibrary();
	new lib.Hello().hello();
}

包目錄結構如下:

  • lib/:源代碼目錄。
    • src/:私有源代碼目錄。
  • pubspec.yaml:配置文件。

flutter包的material.dart:

export 'src/material/app.dart';

main.dart:

import 'package:flutter/material.dart';

void main() {
	runApp(const MyApp());
}

class MyApp extends StatelessWidget {
	const MyApp({super.key});
	
	@override
	Widget build(BuildContext context) {
		return const MaterialApp(
			title: 'Flutter Demo'
		);
	}
}

Add a new 评论

Some HTML is okay.