精华

【转】Flutter 基础语法之Dart语法

2019-09-29  本文已影响0人  Lins_Do

针对当下热门的Flutter跨平台开发语言,Dart语法是其根本,所以这里写了一篇关于Dart语法的文章,希望可以帮到各位快速入门Dart,觉得还不错的朋友麻烦动动手指头给个star支持下,后续会出其他相关的开发教程

Dart语法一天快速入门篇 (Github发布版本)

针对当下热门的Flutter跨平台开发语言,Dart语法是其根本,所以这里写了一篇关于Dart语法的文章,希望可以帮到各位快速入门Dart,觉得还不错的朋友麻烦动动手指头给个star支持下原创作教程,后续会出其他更多相关的开发教程

环境安装篇

Dart本地环境安装(Mac)

如果本地还没安装homebrew的,需要先安装: Homebrew 安装地址

brew tap dart-lang/dart
brew install dart

升级版本 brew upgrade dart

vscode 需要安装 Code runner 和 Dart 两个插件

类型

Dart是强大的脚本类语言,可以不定义变量类型使用var字段(类似JavaScript),系统会自动推导该变量类型 好比 var str = 'hello world' 也可以用 String str = 'hello world' , var a = 1和 int a = 1

常量修饰符final和const

const表示值不变,并且一开始就需要赋值 final也表示该值不能修改,但可以初始化不赋值,但是只能赋值一次

示例代码

final a = new DateTime.now(); print(a);
const b = new DateTime.now(); print(b);

数值类型 String bool List Map类型分析

类型判断 is 和 ??= 和isEmpty

判断是否是某个类型的值, xx is 类型名称

??= 如果左边的类型是null ,则将右边的值赋值给左边, 好比 int a; a??=10; a的最终结果就是10

isEmpty判断字符串是否为空串,如果判断对象是null会报错,例 str.isEmpty(属性不是方法)

类型转换

Dart常用属性以及方法

属性

方法

循环方式

foreach

示例

  var list = ['1','2', '3'];
  var map = {'name':'zhangsan','age':10};

  list.forEach((value){
    print("value is $value");
  });

  map.forEach((key,value){
    print("key is $key , value is $value");
  });

map

说明 :对list中的元素统一操作,例如统一加减乘除等

示例代码

var li = [1, 3, 5];
var newLi = li.map((value){
  return value*2;
});
print(newLi);

where条件

示例代码

var li = [1, 3, 5];
var newLi = li.where((value){
  return value >= 3;
});
print(newLi);

any条件

说明:判断是否对象当中有某个条件成立即返回true,好比列表中大于6的元素是否存在

示例代码

var li = [1, 3, 5];
var flag = li.any((value){
  return value >=6;
});
print(flag);

函数

注意:函数的形参可以不指定类型,返回值也是可以不指定的,但是为了规范写法,一般还是带上特定的类型做修饰,例如无返回使用关键字 void,形参用强类型限定防止外部参数传入任意类型导致出错。

代码片段1


void fn(){
  print('fn invoke');
}

void fn2(fnName) {
  fnName();
}

main() {
  fn2(fn);
}

代码片段2

var fn = (){
  print('hello world');
};

main() {
  fn();
}

main() { 
  var list = ['zhangsan', 'lisi', 'wangwu'];
  list.forEach((value)=>print(value));
}

自执行函数

说明:实际为匿名函数自己调用

  ((){
    print('123');
  })();

闭包

特点:能使变量常住内存并且不会污染全局,既有全局变量的特点也有局部变量的特点

main() {
  func(){
    int a=100;
    return (){
      a++;
      print(a++);
    };
  }

  var func2 = func();
  func2();
  func2();
  func2(); 
}

初始化声明

可以在生成对象的同时初始化内部参数,如下代码片段:


class Rect {
  int width;
  int height;

  //初始化参数
  Rect():width=10,height=10{}

  get area {
    return this.width * this.height;
  }

  set areaWidth(int width) {
    this.width  = width;
  }

}

main() {
  Rect rect = new Rect();
  print(rect.area);
}

Flutter中生成对象通常会省略new关键字,如下代码片段

var rect = Rect();

//类似flutter中返回widget
return Center();//此处省略了new关键字

默认构造函数

默认构造函数跟类名一致,如下代码片段:

class Person{
  String name;
  int age;

  //默认构造函数(只能存在一个默认构造函数)
  Person(String name, int age) {
    this.name = name;
    this.age  = age;
  }
}

以上代码可以简写为如下:

class Person{
  String name;
  int age;

  //默认构造函数(只能存在一个默认构造函数)
  // Person(String name, int age) {
  //   this.name = name;
  //   this.age  = age;
  // }

  //默认构造函数简写
  Person(this.name, this.age);
}

命名构造函数

一个类写多个命名构造函数,写法如下:

class Person{
  String name;
  int age;

  Person.now(String name, int  age) {
    this.name = name;
    this.age  = age;
  }

  Person.now2(String name, int  age) {
    this.name = name;
    this.age  = age;
  }
}

main() {
  Person p = new Person.now('zhangsan', 10);
  Person p2 = new  Person.now2('lisi', 11);
}

类内部的函数中访问类属性

class Person{
  String name;
  int age;

  void printInfo(){
    //通过${this.xxx}
    print('${this.name} , ${this.age}');

    //通过this.xxx
    print(this.name);

    //通过$name
    print('$name');
  }
}

对象操作符

var p;

//这里调用报错,因为p为null
p.getInfo();

//进行非空判断,不会执行getInfo方法 
p?.getInfo();

示例代码

class Person {
  Person(){}

  void printInfo(){
    print("person test");
  }
}

main(){
  var p;
  p = '';
  p = new Person();

  (p as Person).printInfo();

}

class Person {
  String name;
  int age;
  Person(){}

  void printInfo(){
    print("person test");
  }
}

main(){
  Person p = new Person();
  p..name = 'zhangsan'
   ..age  =  10
   ..printInfo();
}

继承

关键字extends

例如 class Teacher extends Person{} 表示Teacher类继承自Person类

调用父类默认的方法 super

class Teacher extends Person {
    //此方式调用父类的默认构造方法
    Teacher(String name, int age): super(name,  age);
}

重写父类方法 @override(可以不加,但是一般会加上)

 class Person {
  void printInfo(){
    print("person test");
  }
}

class Teacher extends Person{

  //采用关键字@override 标记该方法是重写父类的,这点跟Java一样
  @override
  void printInfo() {
    super.printInfo();
  }
}

抽象类

Dart中的抽象类主要用于定义标准,这个跟Java语言有点像,在Dart中,抽象类也可以作为抽象类接口来使用, 抽象类通过关键字 abstract来定义,如果想作为接口来使用定义一套标准,可以用关键字 implements来使用

抽象方法

示例代码

//抽象类 继承的子类必须实现抽象方法
abstract class A {
  printA();

  printAA(){
    print("AA");
  }
}

//接口 实现该接口必须实现 方法+属性
abstract class B {
  String name;
  printB();
}

class C extends A implements B {
  @override
  String name;

  @override
  printA() {
    print('A');
  }

  @override
  printB() {
    print('B');
  }
}

mixins

Dart中有一种方式能实现类似多继承,但实际不是继承,用关键字with

示例代码

class A {
  void printA(){

  }

  void getStr(){
    print("this is A method");
  }
}

class B {
  void printB(){

  }

  void getStr(){
    print("this is B method");
  }
}

class C with A, B {
  @override
  void printA() {
    print("重写的A方法");
  }

  @override
  void printB() {
    print("重写的B方法");
  }
}

void main() {
  C c = new C();
  c.printA();
  c.printB();

  //A和B均有getStr 方法,调用哪个方法取决于with之后写的顺序有关,最后一个会覆盖前面所有的
  c.getStr();  

  print(c is A);  //true 
  print(c is B);  //true
}

访问修饰符

私有属性和方法

Dart中没有像Java语言中有public,private,protected这些访问修饰符,但是我们可以采用下划线_ 把一个属性或者方法定义成私有的,这一点跟Python的语法很像,但是应该注意的一点,当把该声明了私有方法或属性单独抽离为一个文件时,才生效,好比把Person类放在model目录下,然后其他文件引用了这个model,才变成不能访问的私有属性和方法

getter和setter修饰符

以下是最原始的代码片段:


class Rect {
  int width;
  int height;

  Rect(this.width,  this.height);

  // 简单地求面积
  int area() {
    return this.width * this.height;
  }

}

main() {
  Rect rect = new Rect(10, 2);
  print(rect.area());
}

get 关键字修饰


class Rect {
  int width;
  int height;

  Rect(this.width,  this.height);

  // 简单地求面积 通过添加get修饰符,可以把area函数变为属性的访问方式
  get area {
    return this.width * this.height;
  }

}

main() {
  Rect rect = new Rect(10, 2);

  //这里通过属性的访问方式调用方法 
  print(rect.area);
}

set 关键字修饰


class Rect {
  int width;
  int height;

  Rect(this.width,  this.height);

  // 简单地求面积 通过添加get修饰符,可以把area函数变为属性的访问方式
  get area {
    return this.width * this.height;
  }

  set areaWidth(int width) {
    this.width  = width;
  }

}

main() {
  Rect rect = new Rect(10, 2);
  rect.areaWidth = 100;
  //这里通过属性的访问方式调用方法 
  print(rect.area);
}

static

① 说明: 通过static修饰的属性和方法,外部可以通过类名直接调用,例如: Person.name Person.getInfo()

② static修饰的方法不能访问非static修饰的属性

泛型

说明:泛型是对类型的限定,例如List这样就只能传入字符串类型的数据,List这样只能传入int类型的数据

示例代码

main() {
  //可以用var也行
  List<String> list = new List<String>();
  list.add('hello');
  list.add('world');

  //以下这行代码报错
  list.add(1);

  print(list);
}

Map类型指定泛型的如下

main() {
  var map = new Map<String, int>();
  map.addAll({'no':1});

  //以下这行代码报错
  map.addAll({'username':'zhangsan'});

  print(map);
}

修饰方法

说明:修饰方法可以不对类型进行强制检查,能提高函数的复用性

示例代码


T returnValue<T>(T value) {
  return value;
}

main() {
  String name = returnValue('zhangsan');
  int age = returnValue(10);

  print('$name  $age');
}

自定义List泛型输入


class JSList<T> {
  var list = new List<T>();

  add(T value) {
    this.list.add(value);
  }
}

main() {
  var list = JSList<String>();
  list.add('helloworld');

  //以下这行代码报错,因为JSList限定了输入类型
  list.add(123);
}

泛型配合接口实现


abstract class A<T> {
  printInfo(T value);
}

class B<T> implements A<T> {
  @override
  printInfo(T value) {
    print('这是B的输出类型');
  }
}

class C<T> implements A<T> {
  @override
  printInfo(T value) {
    print('这是C的输出类型');
  }
}

main() {
  var b = new B<String>();
  var c = new C<int>();

  b.printInfo('hello world');
  c.printInfo(123);
}

上一篇下一篇

猜你喜欢

热点阅读