前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter Lesson 2: Dart 语法简单介绍

Flutter Lesson 2: Dart 语法简单介绍

作者头像
踏浪
发布2019-07-31 11:07:03
1.8K0
发布2019-07-31 11:07:03
举报
文章被收录于专栏:踏浪的文章踏浪的文章

Dart语法Dart中文】可以说是Google因为为Flutter量身定做的一门语言,所以,我们之前基本上都没有接触过这门语言,在入手Flutter坑的时候,还必须了解一下Dart的语言特性。

Dart官网Dart中文】上面已经有了很详细的说明,我这里只是见多的说说,提取一些重点,以便自己复习以及你们学习。 v

main

每一个.Dart文件都会有一个mian()函数,这个称之为程序的入口文件,这就像是前端ES6语法中的export一样,都要有一个输出。其实,Dart的设计就有一点遵循前端的ES6语法,不过他还结合了一些c语言

代码语言:javascript
复制
// 程序的入口文件
main() {
  /* 或者用这种注释 */
  // main函数输出了一点东西,print 控制台输出
  print('我是main函数,我是程序执行的入口');
}

代码都可以在DartPad上面运行,你也可以自行修改代码,不过不可能需要开着V**才可以访问这个网站。

Dart关键字

关键字的意思就不用多说了,注意上图中的关键字,在变量命名的时候不要使用就行了。

重要的概念(重要)

  • 在Dart中,所有的能够使用变量引用的都是对象,每一个对象都有一个实例,包括但不限于数字,方法,字符串,null。所有的对象都集成于Object类。这个需要注意,这个和JavaScript中的变量还是有很大的差别的
  • 虽然Dart是强类型语言,但变量类型是可选的因为Dart可以自动推断变量类型
  • Dart支持顶层方法(如main方法),也支持类方法或对象方法,同时你也可以在方法内部创建方法
  • Dart支持顶层变量,也支持类变量或对象变量
  • Dart中的私有变量用_开头,有点像JS中我们自定义函数的时候默认_开头的为私有变量
  • Dart中变量可以以字母或下划线开头,后面跟着任意组合的字符或数字,不能使用$,这里面的$一般用于字符串拼接

变量

每一种编程语言都会有变量,Dart也不例外,不过Dart的区别就是其声明变量的方式有多种。

var

最简单的就是使用var关键字,你也可以使用dynamic,表示没有指定变量类型

代码语言:javascript
复制
var name = 'tal';
dynamic number = 0.5;

使用var定义变量,最好是定义局部变量

默认值

如果你在定义了一个变量以后,同时并没有对其进行赋值,那么,这个变量最终的类型会是null(注意不是undefined)。

因为前面我已以及说过了,Dart中所有的变量引用都是对象。

可选类型

在声明变量的时候我们可以加上他的类型,这个是google从TS中吸取到的经验

代码语言:javascript
复制
int number = 1;

String name = 'tal';

使用这种方式定义变量可以是全局变量和局部变量,但是如果是使用var定义变量,最好是用于定义局部变量。

Dart中内置了以下几种类型

  • Number
  • String
  • Boolean
  • List ( means array )
  • Map
  • Rune ( 用于在字符串中表示 Unicode 字符 )
  • Symbol
代码语言:javascript
复制
void main() {
  dynamic a = '没有指定变量类型';
  print(a); // 没有指定变量类型
  
//   number
  var na = 1;
  int nb = 2;
  double nc = 1.2;
  print(na); // 1
  print(nb); // 2
  print(nc); // 1.2

  
//   String
  var sa = 'hello';
  String sb = 'world';
  print(sa); // hello
  print(sb); // world
//   字符串插值,当然,你也可以使用 + 进行字符串拼接
  print('$sa ${sb}'); // hello world
  
//   bool
  var bt = true;
  bool bf = false;
  
//   list
  var arr = [1, 'a', false];
  List<String> arr1 = ['a', 'b', 'c'];
  List<dynamic> arr2 = [1, 'a', true];
  print(arr); // [1, a, false]
  print(arr1); // [a, b, c]
  print(arr2); // [1, a, true]

// map Map 是一个键值对相关的对象,有点像JS中的Object
  var person = {
    "name": '踏浪',
    "sex": '男'
  };
  print(person); // {name: 踏浪, sex: 男}
  
  var company = new Map();
  company['leader'] = '踏浪';
  company['money'] = 10000;
  print(company); // {leader: 踏浪, money: 10000}
  
// runes,Dart 中 使用runes 来获取UTF-32字符集的字符。String的 codeUnitAt and codeUnit属性可以获取UTF-16字符集的字符
  var clapping = '\u{1f44f}';
  print(clapping); // 打印的是拍手emoji的表情
  
// symbols  使用 # 符号获取你 new 的这一个 symbol
// 类似于JS中的Symbol,获取方式有点不同。在Dart项目中,获取你从来用不到Symbol
  print(#s == new Symbol("s")); // true
}

需要注意的是,在Dart中,每一个语句结束必须加上 ; 以表示语句结束

final 与 const

const 就是JS中的const,声明一个变量(一般是常量),从此不再修改。这里把final也放到这里,当然功效也是一样的

代码语言:javascript
复制
void main() {
  var a = 10;
  final b = a;
  const c = 10;

  b = 2;
  c = 4;
}

如果你执行了上面的代码,你将会看到如下的错误

final 在声明的时候更多的声明一个变量,而 const 更多的时候声明的是一个常量,有点像JS中的 letconst,例如在Flutter初始化项目的时候有一个这样的代码。

代码语言:javascript
复制
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

final 与 const的区别

  1. final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量
  2. final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。

函数

Dart中的函数有三种

代码语言:javascript
复制
// 声明返回值类型 int
int add1(int a, int b){
  return a + b;
}

// 不声明返回值类型
add2(int a, int b){
  return a + b;
}

// 使用箭头函数
add3(a, b) => a + b;

void main(){
  print(add1(1, 2)); // 3
  print(add2(1, 1)); // 2
  print(add3('hello ', ' world')); // hello  world
}

需要注意的是,Dart中函数中参数的类型需要有一定的限制,同时numString是不可相加的

代码语言:javascript
复制
void main(){
  print(1+'a'); // Error: The argument type 'String' can't be assigned to the parameter type 'num'. print(1+'a');
}

函数参数

命名参数

命名参数是有两种方式 type key 或者是 key: type 的形式,但是都必须使用 {} 括起来,例如

代码语言:javascript
复制
person({String name, int age}) => print('Hello, my name is $name, i am $age.');

void main(){
  person(name: '踏浪', age: 18);
}

传递参数的时候使用 key: value 的形式即可。

可选位置参数

把一些方法的参数放到 [] 中就变成可选 位置参数了

代码语言:javascript
复制
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

不使用可选参数

代码语言:javascript
复制
print(say('Bob', 'Howdy')) // 'Bob says Howdy'

使用可选参数

代码语言:javascript
复制
print(say('Bob', 'Howdy', 'smoke signal')) // 'Bob says Howdy with a smoke signal'

参数默认值

你可以给参数指定默认值,如果传递了参数,那么取代默认值,否则使用默认值

代码语言:javascript
复制
person(String name = '踏浪') => 'My name is $name'

void main(){
  print(person()); // My name is 踏浪
  print(person('Anthony')); // My name is Anthony
}

入口函数

每一个.dart文件都应该有一个入口函数,即:

代码语言:javascript
复制
void main(){
  // do something
}

// 还可以有一个可选参数,参数类型是 List
void main(List<String> arguments){
  // do something
}

一等对象方法

可以把方法当做参数调用另外一个方法。例如:

代码语言:javascript
复制
printElement(element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);

匿名函数

同样是上面的例子

代码语言:javascript
复制
var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach((element) {
  print(element);
});

forEach方法中的参数函数就是一个匿名函数

函数返回值

所有的函数都有返回值,如果没有指定return语句,那么该函数的返回值为null。

操作符

Dart中的操作符在大部分语言中都是有的,可以看看下面的表格 |描述|操作符| |—|—| |unary postfix| expr++ expr– () [] . ?.| |unary prefix| -expr !expr ~expr ++expr –expr | |multiplicative| / % ~/| |additive| + -| |shift| << >>| |bitwise AND| &| |bitwise XOR| ^| |bitwise OR || |relational and type test| >= > <= < as is is!| |equality| == != | |logical AND| &&| |logical OR| || | |if null| ??| |conditional| expr1 ? expr2 : expr3| |cascade| ..| |assignment| = = /= ~/= %= += -= <<= >>= &= ^= |= ??=|

常见的就可以不用说了,主要说一下在JS中不怎么常见的。

type tset(类型判断)

  • as:类型转换
  • is:类型判断,如果对象是指定的类型怎返回 true = is!:类型转换,与is相反
代码语言:javascript
复制
if (emp is Person) { // 类型检测
  emp.firstName = 'Bob';
}

// 可以使用以下代码简化上面的代码
(emp as Person).firstName = 'Bob';

注意: 上面这两个代码效果是有区别的。如果 emp 是 null 或者不是 Person 类型, 则第一个示例使用 is 则不会执行条件里面的代码,而第二个情况使用 as 则会抛出一个异常。

赋值操作

常用的赋值操作符都是=,dart中有一个??=

代码语言:javascript
复制
a = value;   // 给 a 变量赋值
b ??= value; // 如果 b 是 null,则赋值给 b;
             // 如果不是 null,则 b 的值保持不变

级联操作符(cascade) (..)

级联操作有点像JQ中的链式调用,不同点是JQ的链式调用需要上一个方法返回这个对象自身,而级联操作是不需要的,使用级联操作后,自动返回自身

如果是在web前端中,我们要获取一个元素,修改他的一些属性

代码语言:javascript
复制
var img = document.querySelector('img')
img.alt = '图片'
img.src = 'XXX'
img.width = '100'
img.height = '100'

如果是使用Dart中的..操作符,可以这样写(这里只是以此为例,不一定存在前端中的document等)

代码语言:javascript
复制
document.querySelector('img')
  ..alt = '图片'
  ..src = 'XXX'
  ..width = '100'
  ..height = '100'

流程控制

Dart中的流程控制与前端中的流程控制是一样的,也就以下几种

  • if and if...else
  • for loops
  • while and do-while
  • break and continue
  • switch and case
  • try...catch and try...finally
  • assert

还是有一些不同点的,需要注意

  1. switch...case 语句中,case语句中的数据类型必须是跟switch中的类型一致

Dart中还有一个assert(断言),作用是:如果条件表达式结果不满足需要,则可以使用 assert 语句俩打断代码的执行。

代码语言:javascript
复制
// 确保 text 不是nunll
assert(text != null);

// 确保 number 的值 小于100
assert(number < 100);

但是:断言只在开发环境有效,如果是生产环境,则无效

class 类

前端在ES6中才引入了类的概念,即使用class关键字创建一个类

代码语言:javascript
复制
class Point {
  num x, y = 10;
  num z = 0;

  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}

void main(){
  var p = new Point(1, 3);
 	print(p.x); // 1
  print(p.y);  // 3
  print(p.z); // 0
}

在使用class构建一个类的同时,在定义一个与类名字相同的方法就定义了一个构造函数,如上面的Point类中的Point方法。

由于把构造函数参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操作:

如下面的代码和之前的代码是完全一样的

代码语言:javascript
复制
class Point {
  num x, y = 10;
  num z = 0;

  // 默认的构造方法
  Point(this.x, this.y);
}

void main(){
  var p = new Point(1, 3);
 	print(p.x); // 1
  print(p.y);  // 3
  print(p.z); // 0
}

类的继承

如果你是用过react进行开发前端项目,那么你一定对class ... extends ...非常的属性,不错,Dart中也是使用extends继承的

代码语言:javascript
复制
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)这种写法

重定向构造函数

有时候一个构造函数会调动类中的其他构造函数。 一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号 调用其他构造函数。

代码语言:javascript
复制
class Point {
  num x;
  num y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}

getters and setters

getterssetters 是用来设置和访问对象属性的特殊 函数。每个实例变量都隐含的具有一个 getter, 如果变量不是 final 的则还有一个 setter。 你可以通过实行 gettersetter 来创建新的属性, 使用 getset 关键字定义 gettersetter:

代码语言:javascript
复制
class Rectangle {
  num left;
  num top;
  num width;
  num height;

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

  // Define two calculated properties: right and bottom.
  num get right             => left + width;
      set right(num value)  => left = value - width;
  num get bottom            => top + height;
      set bottom(num value) => top = value - height;
}

main() {
  var rect = new Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}

抽象函数(抽象类)

定义一个抽象类需要使用 abstract 关键字,然后在定义一个方法,类型是 void ,具体是实现,由子类实现

代码语言:javascript
复制
abstract class Doer {
  // ...Define instance variables and methods...

  void doSomething(); // Define an abstract method.
}

class EffectiveDoer extends Doer {
  void doSomething() {
    // ...Provide an implementation, so the method is not abstract here...
  }
}

调用一个没实现的抽象函数会导致运行时异常。

运算符重载

如果你定义了一个 Vector 类, 你可以定义一个 + 函数来实现两个向量相加。

代码语言:javascript
复制
class Vector {
  final int x;
  final int y;
  const Vector(this.x, this.y);

  /// Overrides + (a + b).
  Vector operator +(Vector v) => new Vector(x + v.x, y + v.y);

  /// Overrides - (a - b).
  Vector operator -(Vector v) => new Vector(x - v.x, y - v.y);

  printRes(){
    print('X: $x , Y: $y ');
  }
}

main() {
  final v = new Vector(2, 3);
  final w = new Vector(2, 2);
  (v + w).printRes(); // X: 4 (2+2) , Y: 5(3+2)
  (v - w).printRes(); // X: 0 (2-2) , Y: 1(3-2)
}

枚举类

枚举类型通常称之为 enumerations 或者 enums, 是一种特殊的类,用来表现一个固定数目的常量。使用enum关键字定义

代码语言:javascript
复制
enum Color {
  red,
  green,
  blue
}

枚举类型中的每个值都有一个 index getter 函数, 该函数返回该值在枚举类型定义中的位置(从 0 开始),有点像数组的索引。

枚举类型具有如下的限制:

  • 无法继承枚举类型、无法使用 mixin 、无法实现一个枚举类型
  • 无法显示的初始化一个枚举类型

mixins

Mixins 是一种在多类继承中重用 一个类代码的方法。

使用 with 关键字后面为一个或者多个 mixin 名字来使用 mixin。

代码语言:javascript
复制
class A {
  a() {
    print("A's a()");
  }
}

class B {
  b() {
    print("B's b()");
  }
}

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

main() {
  C c = new C();
  c.a(); // A's a()
  c.b(); // B's b()
}

静态函数与变量

使用 static 关键字来实现类级别的变量和函数。

代码语言:javascript
复制
class Person {
  static String name = '踏浪';
  static sayName() {
    print('我的名字是$name');
  }
}
void main(){
  print(Person.name);
  Person.sayName();
}

可以看到,静态函数与变量我们可以直接调用,而不需要通过 new 实现实例后在进行处理。

Generics(泛型)

代码语言:javascript
复制
var names = new List<String>();

上面的代码中,<...>表示的就是这个List中每一项的类型,上面的代码中是String,表示的就是这个List中的每一项都要是String类型,而不能是其他的类型。

泛型是什么呢?泛型就是这一个对象中的内容可以使任何的类型,通常情况下,在<>中使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V 等。例如<E>

使用泛型的好处:

  • 正确指定泛型类型会产生更好的生成代码。
  • 泛型可以减小代码的复杂度

更多的泛型知识可以点击这里查看

Dart库

使用 import 来指定一个库如何使用另外 一个库。

代码语言:javascript
复制
import 'dart:html'; // 导入 web 组件库
import 'dart:math'; // 导入 数学计算库

更多官方库可以点击查看

我们也可以引用自己的.dart文件,类似于 ES6 中的 import

代码语言:javascript
复制
// add.dart
add(int a, int b) => a + b;

在另一个文件引入

代码语言:javascript
复制
import './add.dart';

void main(){
  print(add(1,2));
}

使用 as 创建别名

代码语言:javascript
复制
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.

使用 show and hide 过滤引入内容

代码语言:javascript
复制
// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;

使用 deferred as 来延时载入库

代码语言:javascript
复制
import 'package:deferred/hello.dart' deferred as hello;

异步支持

Dart支持ES7的 async await 方法

下面的代码使用Dart从网络获取数据并打印出来

代码语言:javascript
复制
import 'dart:async';
import 'package:http/http.dart' as http;

Future<String> getNetData() async{
  http.Response res = await http.get("http://www.baidu.com");
  return res.body;
}

main() {
  getNetData().then((str) {
    print(str);
  });
}

以上就是关于Dart语法的简单介绍,想要了解更多,可以参阅Dart官网

注:参考文献

  1. https://www.jianshu.com/p/06aebcad0543
  2. Dart中文
  3. Dart官网
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • main
  • Dart关键字
  • 重要的概念(重要)
  • 变量
    • var
      • 默认值
        • 可选类型
          • final 与 const
            • final 与 const的区别
        • 函数
          • 函数参数
            • 命名参数
            • 可选位置参数
            • 参数默认值
          • 入口函数
            • 一等对象方法
              • 匿名函数
                • 函数返回值
                • 操作符
                  • type tset(类型判断)
                    • 赋值操作
                      • 级联操作符(cascade) (..)
                        • 流程控制
                        • class 类
                          • 类的继承
                            • 重定向构造函数
                              • getters and setters
                                • 抽象函数(抽象类)
                                  • 运算符重载
                                    • 枚举类
                                      • mixins
                                        • 静态函数与变量
                                        • Generics(泛型)
                                        • Dart库
                                        • 异步支持
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档