Flutter入门知识—Dart语言基础入门

代码练习:DartPad

对比语言:JavaScript

1、程序入口

JavaScript:没有入口函数。

Dart:必须有一个main()函数作为程序入口。

2、控制台输出

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

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

3、dart数据类型

//int (一般占8个字节)                   

var count = 1;   or   int count = 1;

//double (一般占8个字节)           

var a = 0.1;    or    double a =0.1;

//num(int和double的父类型,一般占8个字节)

//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没有long和float类型

4、变量

JavaScript:无法定义变量类型,js没有这种声明方式:int count = 1。

Dart:是类型安全的,你可以明确指定某个变量的类型,如int bool String,也可以用var或 dynamic来声明一个变量。尽管类型是必须的,但是dart的某些类型注释是可选的,因为dart会执行类型推断。Dart 没有 public、private、protected 这些关键字,变量名以"_"开头意味着对它的 lib 是私有的。

例如:

//JavaScript

var name = "JavaScript";

//Dart

String name1 = 'Dart';   或者    var name2 = 'dart';都是可以接受的,其中name2进行了类型推断。

5、默认值

JavaScript:未初始化的变量默认值是undefined。

Dart:未初始化的变量默认值是null。

注意,数字在dart语言中也被当成对象,所以即使是带有数字类型的对象没有给出初始化默认值,那么该对象值就是“null”。

//JavaScript

var name;   // ==undefined

//Dart

String name;  // ==null

int a;    //  ==null

6、检查null或零

JavaScript:1或者任何非null对象的值被视为true。

Dart:只有布尔值为true才被视为true。

// is运算符用于判断一个变量是不是某个类型的数据

// is!则是判断变量不是某个类型的数据

var s ="hello";

print(s is String);// true 

var num =6;

print(num is! String);// true

// ~/是取整运算符,如果使用/则是除法运算,不取整

int k =1; int j =2;

print(k / j);// 0.5

print(k ~/ j);// 0

// as运算符类似于Java中的cast操作,将一个对象强制类型转换

(empasPerson).teach();

// ??=运算符 如果 ??= 运算符前面的变量为null,则赋值,否则不赋值

var param1 ="hello", param2 =null; 

 param1 ??="world"; 

 param2 ??="world";

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

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

// ?.运算符在左边为null的情况下会阻断右边函数的调用

var str1 ="hello world";

var str2 =null;

print(str1?.length);// 11

print(str2?.length);// null 

print(str2.length);// 报错

//??运算符在左侧表达式为null的时候为其设置右边为默认值

print(null??false);//false

print(false??11);//false

print(true??false);//true

7、final和const

如果你绝不想改变一个变量,使用final或const,不要使用var或其他类型,一个被final修饰的变量只能被赋值一次,一个被const修饰的变量是一个编译时常量(const常量毫无疑问也是final常量)。可以这么理解:final修饰的变量是不可改变的,而const修饰的表示一个常量。

注意:实例变量可以是final的但不能是const的

说明:

var count =10;

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

const Num1 =10;// const赋值必须是编译时常量

final和const的区别:

区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。

区别二:final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。

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语句的简写

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

main() {

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

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

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

}

9、命名参数、位置参数、参数默认值

命名参数

定义命名参数时,你可以以 {type paramName} 或者 {paramName: type} 两种方式声明参数,而调用命名参数时,需要以 funcName(paramName: paramValue) 的形式调用

注意:命名参数被{ }括了起来,类似于map的形式,调用的时候需要 参数名:参数值

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');}

位置参数

使用中括号[]括起来的参数是函数的位置参数,代表该参数可传可不传,位置参数只能放在函数的参数列表的最后面,如下代码所示:

sayHello(String name, int age, [String hobby]) {// 位置参数可以有多个,比如[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");

}

参数默认值

// 命名参数的默认值

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

return a + b;

}

// 位置参数的默认值

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

return a + b + c;

}

10、

类的定义与构造方法

Dart中的类没有访问控制,所以你不需要用private, protected, public等修饰成员变量或成员函数,一个简单的类如下代码所示:

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类中有3个成员变量,一个构造方法和一个成员方法,看起来比较奇怪的是Person的构造方法,里面传入的3个参数都是this.xxx,而且是没有大括号{}包裹的方法体,这种语法是Dart比较独特而简洁的构造方法声明方式,它等同于下面的代码:

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

this.name = name;

this.age = age;

this.gender = gender;

}

要调用Person类的成员变量或成员方法,可以用下面的代码:

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

类除了有跟类名相同的构造方法外,还可以添加命名的构造方法,如下代码所示:

class Point{ 

num x, y; 

Point(this.x,this.y);

// 类的命名构造方法

Point.origin() {  

  x =0;  

  y =0;  

 }

}

main() {

// 调用Point类的命名构造方法origin()

var p =new Point.origin();

var p2 =new Point(1,2);

}

Dart中使用extends关键字做类的继承,如果一个类只有命名的构造方法,在继承时需要注意,如下代码:

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类没有默认构造方法,只有一个命名构造方法fromJson,所以在Man类继承Human类时,需要调用父类的fromJson方法做初始化,而且必须使用Man.fromJson(Map data) : super.fromJson(data)这种写法,而不是像Java那样将super写到花括号中。

有时候你仅仅只是在某个类的构造方法中,调用这个类的另一个构造方法,你可以这么写:

class Point{

num x, y;

Point(this.x,this.y);

// 命名构造方法调用了默认的构造方法

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

类的成员方法

一个类的成员方法是一个函数,为这个类提供某些行为。上面的代码中已经有了一些类的成员方法的定义,这些定义方式跟Java很类似,你可以为某个类的成员变量提供getter/setter方法,如下代码:

class Rectangle{

num left, top, width, height;// 

构造方法传入left, top, width, height几个参数

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

// right, bottom两个成员变量提供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;

}

抽象类和抽象方法

使用abstract修饰一个类,则这个类是抽象类,抽象类中可以有抽象方法和非抽象方法,抽象方法没有方法体,需要子类去实现,如下代码:

abstract class Doer{

// 抽象方法,没有方法体,需要子类去实现

void doSomething();

// 普通的方法

void greet(){ 

  print("hello world!");  

}}

class EffectiveDoer extends Doer{

// 实现了父类的抽象方法

void doSomething(){ 

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

 }}

运算符重载

Dart中有类似于C++中的运算符重载语法,比如下面的代码定义了一个向量类,重载了向量的+ -运算:

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

}

枚举类

使用enum关键字定义一个枚举类,这个语法跟Java类似,如下代码:

enum Color { red, green, blue }

mixins

mixins是一个重复使用类中代码的方式,比如下面的代码:

classA{  

a() {

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

}

}

classB{ 

 b() {   

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

}

}

// 使用with关键字,表示类C是由类A和类B混合而构成

classC= A with B;

main() { 

 C c =new C();  

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

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

}

静态成员变量和静态成员方法

// 类的静态成员变量和静态成员方法

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一样,都支持单线程执行

JavaScript:promise对象表示异步操作的最终完成(或失败)及其结果值

Dart:future来表示异步操作

12、async和await

async函数声明定义了一个异步函数。

JavaScript:async函数返回一个promise,await运算符用来等待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函数返回一个future,函数的主体是稍后执行,await运算符用来等待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);

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容