Flutter入門(mén)知識(shí)—Dart語(yǔ)言基礎(chǔ)入門(mén)

代碼練習(xí):DartPad

對(duì)比語(yǔ)言:JavaScript

1、程序入口

JavaScript:沒(méi)有入口函數(shù)。

Dart:必須有一個(gè)main()函數(shù)作為程序入口。

2、控制臺(tái)輸出

JavaScript:console.log("hello,world!");

Dart:print('hello,world!');

3、dart數(shù)據(jù)類(lèi)型

//int (一般占8個(gè)字節(jié))? ? ? ? ? ? ? ? ? ?

var count = 1;? ?or? ?int count = 1;

//double (一般占8個(gè)字節(jié))? ? ? ? ? ?

var a = 0.1;? ? or? ??double a =0.1;

//num(int和double的父類(lèi)型,一般占8個(gè)字節(jié))

//String? ? ? ? ? ? ? ? ? ? ??

?var s = "dart"; or String s = 'dart';

//bool? ? ? ? ? ? ? ? ? ? ? ? ? ??

var find = true; or??bool find = true;

//List?

var arr = [1,2,3,4,5];??

List<String>?arr2 = ['hello','world',"123","456"];??

List flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];

//Map? ? ??

var image = new Map();

var image = { 'tags': ['saturn'], 'url': '//path/to/xxx.jpg'};?

var map={"a":"1","b":2,"c":3,4:5};

Map image = { 'tags': ['saturn'], 'url': '//path/to/xxx.jpg'};

注意:dart沒(méi)有l(wèi)ong和float類(lèi)型

4、變量

JavaScript:無(wú)法定義變量類(lèi)型,js沒(méi)有這種聲明方式:int count = 1。

Dart:是類(lèi)型安全的,你可以明確指定某個(gè)變量的類(lèi)型,如int bool String,也可以用var或 dynamic來(lái)聲明一個(gè)變量。盡管類(lèi)型是必須的,但是dart的某些類(lèi)型注釋是可選的,因?yàn)?b>dart會(huì)執(zhí)行類(lèi)型推斷。Dart 沒(méi)有 public、private、protected 這些關(guān)鍵字,變量名以"_"開(kāi)頭意味著對(duì)它的 lib 是私有的。

例如:

//JavaScript

var name = "JavaScript";

//Dart

String name1 = 'Dart';? ?或者? ? var name2 = 'dart';都是可以接受的,其中name2進(jìn)行了類(lèi)型推斷。

5、默認(rèn)值

JavaScript:未初始化的變量默認(rèn)值是undefined。

Dart:未初始化的變量默認(rèn)值是null。

注意,數(shù)字在dart語(yǔ)言中也被當(dāng)成對(duì)象,所以即使是帶有數(shù)字類(lèi)型的對(duì)象沒(méi)有給出初始化默認(rèn)值,那么該對(duì)象值就是“null”。

//JavaScript

var name;? ?// ==undefined

//Dart

String name;? // ==null

int a;? ? //? ==null

6、檢查null或零

JavaScript:1或者任何非null對(duì)象的值被視為true。

Dart:只有布爾值為true才被視為true。

// is運(yùn)算符用于判斷一個(gè)變量是不是某個(gè)類(lèi)型的數(shù)據(jù)

// is!則是判斷變量不是某個(gè)類(lèi)型的數(shù)據(jù)

var s ="hello";

print(s is String);// true?

var num =6;

print(num is! String);// true

// ~/是取整運(yùn)算符,如果使用/則是除法運(yùn)算,不取整

int k =1; int j =2;

print(k / j);// 0.5

print(k ~/ j);// 0

// as運(yùn)算符類(lèi)似于Java中的cast操作,將一個(gè)對(duì)象強(qiáng)制類(lèi)型轉(zhuǎn)換

(empasPerson).teach();

// ??=運(yùn)算符?如果 ??= 運(yùn)算符前面的變量為null,則賦值,否則不賦值

var param1 ="hello", param2 =null;?

?param1 ??="world";?

?param2 ??="world";

print("param1 = $param1");// param1 = hello?

print("param2 = $param2");// param2 = world

//??.運(yùn)算符在左邊為null的情況下會(huì)阻斷右邊函數(shù)的調(diào)用

var str1 ="hello world";

var str2 =null;

print(str1?.length);// 11

print(str2?.length);// null?

print(str2.length);// 報(bào)錯(cuò)

//??運(yùn)算符在左側(cè)表達(dá)式為null的時(shí)候?yàn)槠湓O(shè)置右邊為默認(rèn)值

print(null??false);//false

print(false??11);//false

print(true??false);//true

7、final和const

如果你絕不想改變一個(gè)變量,使用final或const,不要使用var或其他類(lèi)型,一個(gè)被final修飾的變量只能被賦值一次,一個(gè)被const修飾的變量是一個(gè)編譯時(shí)常量(const常量毫無(wú)疑問(wèn)也是final常量)。可以這么理解:final修飾的變量是不可改變的,而const修飾的表示一個(gè)常量。

注意:實(shí)例變量可以是final的但不能是const的

說(shuō)明:

var count =10;

final Num = count;// final 只能賦值一次

const Num1 =10;// const賦值必須是編譯時(shí)常量

final和const的區(qū)別:

區(qū)別一:final 要求變量只能初始化一次,并不要求賦的值一定是編譯時(shí)常量,可以是常量也可以不是。而 const 要求在聲明時(shí)初始化,并且賦值必需為編譯時(shí)常量。

區(qū)別二:final 是惰性初始化,即在運(yùn)行時(shí)第一次使用前才初始化。而 const 是在編譯時(shí)就確定值了。

8、function

//JavaScript

function fn(){
return true;

}

//Dart

// 聲明返回值

int add(int a,int b){

return a + b;

}

// 不聲明返回值

add2(int a,int b) {

return a + b;

}

// =>是return語(yǔ)句的簡(jiǎn)寫(xiě)

add3(a, b) => a + b;

main() {

print(add(1,2));// 3

print(add2(2,3));// 5

print(add3(1,2));// 3

}

9、命名參數(shù)、位置參數(shù)、參數(shù)默認(rèn)值

命名參數(shù)

定義命名參數(shù)時(shí),你可以以?{type paramName}?或者?{paramName: type}?兩種方式聲明參數(shù),而調(diào)用命名參數(shù)時(shí),需要以?funcName(paramName: paramValue)?的形式調(diào)用

注意:命名參數(shù)被{ }括了起來(lái),類(lèi)似于map的形式,調(diào)用的時(shí)候需要 參數(shù)名:參數(shù)值

sayHello({String name}) {

print("hello, my name is $name");

}

sayHello2({name: String}) {

print("hello, my name is $name");

}

main() {?

// 打印 hello, my name is zhangsan??

sayHello(name:'zhangsan');??

// 打印 hello, my name is wangwu?

?sayHello2(name:'wangwu');}

位置參數(shù)

使用中括號(hào)[]括起來(lái)的參數(shù)是函數(shù)的位置參數(shù),代表該參數(shù)可傳可不傳,位置參數(shù)只能放在函數(shù)的參數(shù)列表的最后面,如下代碼所示:

sayHello(String name, int age, [String hobby]) {// 位置參數(shù)可以有多個(gè),比如[String a, int b]

StringBuffer sb =new StringBuffer();?

sb.write("hello, this is $name and I am $age years old");

if(hobby !=null) {?

?sb.write(", my hobby is $hobby");

?}

print(sb.toString());

}

main() {

// hello, this is zhangsan and I am 20 years old

sayHello("zhangsan",20);

// hello, this is zhangsan and I am 20 years old, my hobby is play football

sayHello("zhangsan",20,"play football");

}

參數(shù)默認(rèn)值

// 命名參數(shù)的默認(rèn)值

int add({int a, int b =3}){// 不能寫(xiě)成:int add({a: int, b: int = 3})

return a + b;

}

// 位置參數(shù)的默認(rèn)值

int sum(int a,int b, [int c =3]){

return a + b + c;

}

10、類(lèi)

類(lèi)的定義與構(gòu)造方法

Dart中的類(lèi)沒(méi)有訪問(wèn)控制,所以你不需要用private, protected, public等修飾成員變量或成員函數(shù),一個(gè)簡(jiǎn)單的類(lèi)如下代碼所示:

class Person{

String name;?

int age;

String gender;

Person(this.name,this.age,this.gender);?

sayHello() {

? ? print("hello, this is $name, I am $age years old, I am a $gender");

?}

}

上面的Person類(lèi)中有3個(gè)成員變量,一個(gè)構(gòu)造方法和一個(gè)成員方法,看起來(lái)比較奇怪的是Person的構(gòu)造方法,里面?zhèn)魅氲?個(gè)參數(shù)都是this.xxx,而且是沒(méi)有大括號(hào){}包裹的方法體,這種語(yǔ)法是Dart比較獨(dú)特而簡(jiǎn)潔的構(gòu)造方法聲明方式,它等同于下面的代碼:

Person(String name, int age,String gender) {

this.name = name;

this.age = age;

this.gender = gender;

}

要調(diào)用Person類(lèi)的成員變量或成員方法,可以用下面的代碼:

var p =new Person("zhangsan",20,"male");?

p.sayHello();// hello, this is zhangsan, I am 20 years old, I am a male

p.age =50;??

p.gender ="female";??

p.sayHello();// hello, this is zhangsan, I am 50 years old, I am a female

類(lèi)除了有跟類(lèi)名相同的構(gòu)造方法外,還可以添加命名的構(gòu)造方法,如下代碼所示:

class Point{?

num x, y;?

Point(this.x,this.y);

// 類(lèi)的命名構(gòu)造方法

Point.origin() {??

? x =0;??

? y =0;??

?}

}

main() {

// 調(diào)用Point類(lèi)的命名構(gòu)造方法origin()

var p =new Point.origin();

var p2 =new Point(1,2);

}

Dart中使用extends關(guān)鍵字做類(lèi)的繼承,如果一個(gè)類(lèi)只有命名的構(gòu)造方法,在繼承時(shí)需要注意,如下代碼:

class Human{

String name;?

Human.fromJson(Map data) {? ?

print("Human's fromJson constructor");?

?}

}

class Man extends Human{??

Man.fromJson(Map data) :super.fromJson(data) {??

? print("Man's fromJson constructor");?

?}

}

由于Human類(lèi)沒(méi)有默認(rèn)構(gòu)造方法,只有一個(gè)命名構(gòu)造方法fromJson,所以在Man類(lèi)繼承Human類(lèi)時(shí),需要調(diào)用父類(lèi)的fromJson方法做初始化,而且必須使用Man.fromJson(Map data) : super.fromJson(data)這種寫(xiě)法,而不是像Java那樣將super寫(xiě)到花括號(hào)中。

有時(shí)候你僅僅只是在某個(gè)類(lèi)的構(gòu)造方法中,調(diào)用這個(gè)類(lèi)的另一個(gè)構(gòu)造方法,你可以這么寫(xiě):

class Point{

num x, y;

Point(this.x,this.y);

// 命名構(gòu)造方法調(diào)用了默認(rèn)的構(gòu)造方法

Point.alongXAxis(num x) :this(x,0);}

類(lèi)的成員方法

一個(gè)類(lèi)的成員方法是一個(gè)函數(shù),為這個(gè)類(lèi)提供某些行為。上面的代碼中已經(jīng)有了一些類(lèi)的成員方法的定義,這些定義方式跟Java很類(lèi)似,你可以為某個(gè)類(lèi)的成員變量提供getter/setter方法,如下代碼:

class Rectangle{

num left, top, width, height;//?

構(gòu)造方法傳入left, top, width, height幾個(gè)參數(shù)

Rectangle(this.left,this.top,this.width,this.height);

// right, bottom兩個(gè)成員變量提供getter/setter方法

num get right => left + width;

set right(num value)=> left = value - width;??

num get bottom => top + height;

set bottom(num value)=> top = value - height;

}

抽象類(lèi)和抽象方法

使用abstract修飾一個(gè)類(lèi),則這個(gè)類(lèi)是抽象類(lèi),抽象類(lèi)中可以有抽象方法和非抽象方法,抽象方法沒(méi)有方法體,需要子類(lèi)去實(shí)現(xiàn),如下代碼:

abstract class Doer{

// 抽象方法,沒(méi)有方法體,需要子類(lèi)去實(shí)現(xiàn)

void doSomething();

// 普通的方法

void greet(){?

? print("hello world!");??

}}

class EffectiveDoer extends Doer{

// 實(shí)現(xiàn)了父類(lèi)的抽象方法

void doSomething(){?

?? print("I'm doing something...");?

?}}

運(yùn)算符重載

Dart中有類(lèi)似于C++中的運(yùn)算符重載語(yǔ)法,比如下面的代碼定義了一個(gè)向量類(lèi),重載了向量的+ -運(yùn)算:

class Vector{?

num x, y;??

Vector(this.x,this.y);?

?Vector operator +(Vector v) =>new Vector(x + v.x, y + v.y);?

?Vector operator -(Vector v) =>new Vector(x - v.x, y - v.y);?

?printVec() {?

?? print("x: $x, y: $y");? }}

main() {?

Vector v1 =newVector(1,2);??

Vector v2 =new Vector(3,4);??

(v1 - v2).printVec();? // -2, -2

(v1 + v2).printVec();? // 4, 6

}

枚舉類(lèi)

使用enum關(guān)鍵字定義一個(gè)枚舉類(lèi),這個(gè)語(yǔ)法跟Java類(lèi)似,如下代碼:

enum Color { red, green, blue }

mixins

mixins是一個(gè)重復(fù)使用類(lèi)中代碼的方式,比如下面的代碼:

classA{??

a() {

? ? print("A's a()");??

}

}

classB{?

?b() {? ?

?print("B's b()");??

}

}

// 使用with關(guān)鍵字,表示類(lèi)C是由類(lèi)A和類(lèi)B混合而構(gòu)成

classC= A with B;

main() {?

?C c =new C();??

c.a();? // A's a()

c.b();? // B's b()

}

靜態(tài)成員變量和靜態(tài)成員方法

// 類(lèi)的靜態(tài)成員變量和靜態(tài)成員方法

class Cons{

static const name ="zhangsan";

static sayHello() {

print("hello, this is ${Cons.name}");

? }

}

main() {??

Cons.sayHello(); // hello, this is zhangsan

print(Cons.name); // zhangsan

}

11、異步編程

Dart和JavaScript一樣,都支持單線程執(zhí)行

JavaScript:promise對(duì)象表示異步操作的最終完成(或失?。┘捌浣Y(jié)果值

Dart:future來(lái)表示異步操作

12、async和await

async函數(shù)聲明定義了一個(gè)異步函數(shù)。

JavaScript:async函數(shù)返回一個(gè)promise,await運(yùn)算符用來(lái)等待promise。

async? _getIPAdress(){
?const url = "https://httpbin.org/ip";

const response = await fetch(url);

const json = await respons.json();

const data = await json.origin;

console.log(data);

}

Dart:async函數(shù)返回一個(gè)future,函數(shù)的主體是稍后執(zhí)行,await運(yùn)算符用來(lái)等待future。

_getIPAdress() async{

final?url = "https://httpbin.org/ip";

var request = await HttpRequest.request(url);

String ip = json.decode(request.response.responseText)['origin'];

print(ip);

}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容