printInteger(int a) {
print('Hello world, this is $a.');
}
main() {
var number = 2019;
printInteger(number);
}
——————————————————————————————————————————————————————————————————————————————
Hello world, this is 2019.
int x = 1;
int hex = 0xEEADBEEF;
double y = 1.1;
double exponents = 1.13e5;
int roundY = y.round();
// 檢查是否爲0,在 Dart 中需要顯示地與 0 做比較
var number = 0;
assert(number == 0);
// assert(number); 錯誤
var s = 'cat';
var s1 = 'this is a uppercased string: ${s.toUpperCase()}';
var s2 = 'Hello' + ' ' + 'World!' ;
var s3 = """This is a
multi-line string.""";
var arr1 = ["Tom", "Andy", "Jack"];
var arr2 = List.of([1,2,3]);
arr2.add(499);
arr2.forEach((v) => print('${v}'));
var map1 = {"name": "Tom", 'sex': 'male'};
var map2 = new Map();
map2['name'] = 'Tom';
map2['sex'] = 'male';
map2.forEach((k,v) => print('${k}: ${v}'));
var arr1 = <String>['Tom', 'Andy', 'Jack'];
var arr2 = new List<int>.of([1,2,3]);
arr2.add(499);
arr2.forEach((v) => print('${v}'));
print(arr2 is List<int>); // true
var map1 = <String, String>{'name': 'Tom','sex': 'male',};
var map2 = new Map<String, String>();
map2['name'] = 'Tom';
map2['sex'] = 'male';
map2.forEach((k,v) => print('${k}: ${v}'));
print(map2 is Map<String, String>); // true
final name = 'Andy';
const count = 3;
var x = 70;
var y = 30;
final z = x / y;
bool isZero(int number) { //判斷整數是否爲0
return number == 0;
}
void printInfo(int number,Function check) { //用check函數來判斷整數是否爲0
print("$number is Zero: ${check(number)}");
}
Function f = isZero;
int x = 10;
int y = 0;
printInfo(x,f); // 輸出 10 is Zero: false
printInfo(y,f); // 輸出 0 is Zero: true
bool isZero(int number) => number == 0;
void printInfo(int number,Function check) => print("$number is Zero: ${check(number)}");
//要達到可選命名參數的用法,那就在定義函數的時候給參數加上 {}
void enable1Flags({bool bold, bool hidden}) => print("$bold , $hidden");
//定義可選命名參數時增加預設值
void enable2Flags({bool bold = true, bool hidden = false}) => print("$bold ,$hidden");
//可忽略的參數在函數定義時用[]符號指定
void enable3Flags(bool bold, [bool hidden]) => print("$bold ,$hidden");
//定義可忽略參數時增加預設值
void enable4Flags(bool bold, [bool hidden = false]) => print("$bold ,$hidden");
//可選命名參數函數呼叫
enable1Flags(bold: true, hidden: false); //true, false
enable1Flags(bold: true); //true, null
enable2Flags(bold: false); //false, false
//可忽略參數函數呼叫
enable3Flags(true, false); //true, false
enable3Flags(true,); //true, null
enable4Flags(true); //true, false
enable4Flags(true,true); // true, true
class Point {
num x, y;
static num factor = 0;
//語法糖,等同於在函數體內:this.x = x;this.y = y;
Point(this.x,this.y);
void printInfo() => print('($x, $y)');
static void printZValue() => print('$factor');
}
var p = new Point(100,200); // new 關鍵字可以省略
p.printInfo(); // 輸出(100, 200);
Point.factor = 10;
Point.printZValue(); // 輸出10
類的範例化需要根據參數提供多種初始化方式。除了可選命名參數和可選參數之外,Dart 還提供了命名建構函式的方式,
與 C++ 類似,Dart 支援初始化列表。在建構函式的函數體真正執行之前,你還有機會給範例變數賦值,甚至重定向至另一個建構函式。
Point 類中有兩個建構函式 Point.bottom 與 Point,其中:Point.bottom 將其成員變數的初始化重定向到了 Point 中,而 Point 則在初始化列表中爲 z 賦上了預設值 0。
class Point {
num x, y, z;
Point(this.x, this.y) : z = 0; // 初始化變數z
Point.bottom(num x) : this(x, 0); // 重定向建構函式
void printInfo() => print('($x,$y,$z)');
}
var p = Point.bottom(100);
p.printInfo(); // 輸出(100,0,0)
class Point {
num x = 0, y = 0;
void printInfo() => print('($x,$y)');
}
//Vector繼承自Point
class Vector extends Point{
num z = 0;
@override
void printInfo() => print('($x,$y,$z)'); //覆寫了printInfo實現
}
//Coordinate是對Point的介面實現
class Coordinate implements Point {
num x = 0, y = 0; //成員變數需要重新宣告
void printInfo() => print('($x,$y)'); //成員函數需要重新宣告實現
}
var xxx = Vector();
xxx
..x = 1
..y = 2
..z = 3; //級聯運算子,等同於xxx.x=1; xxx.y=2;xxx.z=3;
xxx.printInfo(); //輸出(1,2,3)
var yyy = Coordinate();
yyy
..x = 1
..y = 2; //級聯運算子,等同於yyy.x=1; yyy.y=2;
yyy.printInfo(); //輸出(1,2)
print (yyy is Point); //true
print(yyy is Coordinate); //true
除了繼承和介面實現之外,Dart 還提供了另一種機制 機製來實現類的複用,即「混入」(Mixin)。
混入鼓勵程式碼重用,可以被視爲具有實現方法的介面。這樣一來,不僅可以解決 Dart 缺少對多重繼承的支援問題,還能夠避免由於多重繼承可能導致的歧義(菱形問題)。
備註:繼承歧義,也叫菱形問題,是支援多繼承的程式語言中一個相當棘手的問題。當 B 類和 C 類繼承自 A 類,而 D 類繼承自 B 類和 C 類時會產生歧義。如果 A 中有一個方法在 B 和 C 中已經覆寫,而 D 沒有覆寫它,那麼 D 繼承的方法的版本是 B 類,還是 C 類的呢?
要使用混入,只需要 with 關鍵字即可。
class Coordinate with Point {
}
var yyy = Coordinate();
print (yyy is Point); //true
print(yyy is Coordinate); //true
class Vector {
num x, y;
Vector(this.x, this.y);
// 自定義相加運算子,實現向量相加
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
// 覆寫相等運算子,判斷向量相等
bool operator == (dynamic v) => x == v.x && y == v.y;
}
final x = Vector(3, 3);
final y = Vector(2, 2);
final z = Vector(1, 1);
print(x == (y + z)); // 輸出true
//定義商品Item類
class Item {
double price;
String name;
Item(name, price) {
this.name = name;
this.price = price;
}
}
//定義購物車類
class ShoppingCart {
String name;
DateTime date;
String code;
List<Item> bookings;
price() {
double sum = 0.0;
for(var i in bookings) {
sum += i.price;
}
return sum;
}
ShoppingCart(name, code) {
this.name = name;
this.code = code;
this.date = DateTime.now();
}
getInfo() {
return '購物車資訊:' +
'\n-----------------------------' +
'\n使用者名稱: ' + name+
'\n優惠碼: ' + code +
'\n總價: ' + price().toString() +
'\n日期: ' + date.toString() +
'\n-----------------------------';
}
}
void main() {
ShoppingCart sc = ShoppingCart('張三', '123456');
sc.bookings = [Item('蘋果',10.0), Item('鴨梨',20.0)];
print(sc.getInfo());
}
————————————————————————————————————————————————————————————
購物車資訊:
-----------------------------
使用者名稱: 張三
優惠碼: 123456
總價: 30.0
日期: 2019-06-01 17:17:57.004645
-----------------------------
class Item {
double price;
String name;
Item(this.name, this.price);
}
class ShoppingCart {
String name;
DateTime date;
String code;
List<Item> bookings;
price() {...}
//刪掉了建構函式函數體
ShoppingCart(this.name, this.code) : date = DateTime.now();
...
}
class Meta {
double price;
String name;
Meta(this.name, this.price);
}
class Item extends Meta{
Item(name, price) : super(name, price);
}
class ShoppingCart extends Meta{
DateTime date;
String code;
List<Item> bookings;
double get price {...}
ShoppingCart(name, this.code) : date = DateTime.now(),super(name,0);
getInfo() {...}
}
double get price {
double sum = 0.0;
for(var i in bookings) {
sum += i.price;
}
return sum;
}
class Item extends Meta{
...
//過載了+運算子,合併商品爲套餐商品
Item operator+(Item item) => Item(name + item.name, price + item.price);
}
class ShoppingCart extends Meta{
...
//把迭代求和改寫爲歸納合並
double get price => bookings.reduce((value, element) => value + element).price;
...
getInfo() {...}
}
getInfo () => '''
購物車資訊:
-----------------------------
使用者名稱: $name
優惠碼: $code
總價: $price
Date: $date
-----------------------------
''';
ShoppingCart sc = ShoppingCart('張三', '123456') ;
class ShoppingCart extends Meta{
...
//預設初始化方法,轉發到withCode裡
ShoppingCart({name}) : this.withCode(name:name, code:null);
//withCode初始化方法,使用語法糖和初始化列表進行賦值,並呼叫父類別初始化方法
ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);
//??運算子表示爲code不爲null,則用原值,否則使用預設值"沒有"
getInfo () => '''
購物車資訊:
-----------------------------
使用者名稱: $name
優惠碼: ${code??"沒有"}
總價: $price
Date: $date
-----------------------------
''';
}
void main() {
ShoppingCart sc = ShoppingCart.withCode(name:'張三', code:'123456');
sc.bookings = [Item('蘋果',10.0), Item('鴨梨',20.0)];
print(sc.getInfo());
ShoppingCart sc2 = ShoppingCart(name:'李四');
sc2.bookings = [Item('香蕉',15.0), Item('西瓜',40.0)];
print(sc2.getInfo());
}
-----------------------------------------------------------------------
購物車資訊:
-----------------------------
使用者名稱: 張三
優惠碼: 123456
總價: 30.0
Date: 2019-06-01 19:59:30.443817
-----------------------------
購物車資訊:
-----------------------------
使用者名稱: 李四
優惠碼: 沒有
總價: 55.0
Date: 2019-06-01 19:59:30.451747
-----------------------------
abstract class PrintHelper {
printInfo() => print(getInfo());
getInfo();
}
class ShoppingCart extends Meta with PrintHelper{
...
}
void main() {
ShoppingCart.withCode(name:'張三', code:'123456')
..bookings = [Item('蘋果',10.0), Item('鴨梨',20.0)]
..printInfo();
ShoppingCart(name:'李四')
..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
..printInfo();
}
class Meta {
double price;
String name;
//成員變數初始化語法糖
Meta(this.name, this.price);
}
class Item extends Meta{
Item(name, price) : super(name, price);
//過載+運算子,將商品物件合併爲套餐商品
Item operator+(Item item) => Item(name + item.name, price + item.price);
}
abstract class PrintHelper {
printInfo() => print(getInfo());
getInfo();
}
//with表示以非繼承的方式複用了另一個類的成員變數及函數
class ShoppingCart extends Meta with PrintHelper{
DateTime date;
String code;
List<Item> bookings;
//以歸納合並方式求和
double get price => bookings.reduce((value, element) => value + element).price;
//預設初始化函數,轉發至withCode函數
ShoppingCart({name}) : this.withCode(name:name, code:null);
//withCode初始化方法,使用語法糖和初始化列表進行賦值,並呼叫父類別初始化方法
ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);
//??運算子表示爲code不爲null,則用原值,否則使用預設值"沒有"
@override
getInfo() => '''
購物車資訊:
-----------------------------
使用者名稱: $name
優惠碼: ${code??"沒有"}
總價: $price
Date: $date
-----------------------------
''';
}
void main() {
ShoppingCart.withCode(name:'張三', code:'123456')
..bookings = [Item('蘋果',10.0), Item('鴨梨',20.0)]
..printInfo();
ShoppingCart(name:'李四')
..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
..printInfo();
}