Dart语言基础

1.1、基本数据类型

1.1.1、Number

Dart 语言的 Number 有两种类型:

int: 整数值不大于64位, 具体取决于平台

double: 64位(双精度)浮点数

// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

1.1.2、String

Dart 字符串是一组 UTF-16 单元序列。 字符串通过单引号或者双引号创建。

 var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";

字符串可以通过 ${expression} 的方式内嵌表达式。 如果表达式是一个标识符,则 {} 可以省略。 在 Dart 中通过调用就对象的toString() 方法来得到对象相应的字符串。可以使用 + 运算符来把多个字符串连接为一个,使用连续三个单引号或者三个双引号实现多行字符串对象的创建

var name = 'dart';
var s1 = 's is $name';
var s2= 's is $name' + 'language';
var s3 = '''
You can create
multi-line strings like this one.
''';

1.1.3、Boolean

Dart 使用 bool 类型表示布尔值。 Dart 只有字面量 true and false 是布尔类型

1.1.4、List

var list = [1, 2, 3];
List list2 = [1, 2, 3,'ss']; //List<dynamic> list2 = [1, 2, 3,'ss'];
list2.remove(2);
list2.clear();
list2.add(2);
list2.addAll(['a', 'b']);

1.1.5、Map

Map 是用来关联 keys 和 values 的对象。 keys 和 values 可以是任何类型的对象。

//Map<String, String> 
var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

//Map<int, String> 
var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

//Map<dynamic, String> 
Map nobles = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
  'name' : 'dart',
};

1.2、变量

  • 任何保存在变量中的都是一个 对象 , 并且所有的对象都是对应一个 的实例。 无论是数字,函数和 null 都是对象。所有对象继承自 Object 类。
  • 使用过程中从来不会被修改的变量, 可以使用 final 或 const, 可被修改的变量是 var 或者其他类型, Final 变量的值只能被设置一次; Const 变量在编译时就已经固定
var name = 'Bob';
String name2 = "Bob";

final name3 = 'name3';
// final String name3 = 'name3';
// name3 = "pop"; //The final variable 'name3' can only be set once.

const name4 = 'name4';
// name4 = "pop"; //Constant variables can't be assigned a value.

final name5;
name5 = "name5";
// name5 = 'pop'; //The final variable 'name5' can only be set once.

// const name6; //The constant 'name6' must be initialized.

1.3、构造函数

1.3.1、默认构造函数

类里面没有显示写构造函数,默认是一个隐式的无参构造函数

1.3.2、 普通构造函数

指定一个类名相同的方法就是普通构造函数

class Test{
  int a, b;
  Test(int a, int b){
    this.a = a;
    this.b = b;
  }
}

可以将上述直接简写为

class Test{
  int a, b;
  Test(this.a, this.b);
}

1.3.3、 命名构造函数

命名构造函数就是给构造函数添加个名字,使用命名构造函数可为一个类实现多个构造函数, 也可以使用命名构造函数来更清晰的表明函数意图:,比如从json转model时常用的fromJson就是命名构造函数, 命名构造函数不可以继承

class Test{
  int a, b;
  Test(this.a, this.b);
  
  Test.fromJson(int a, int b){
    this.a = a;
    this.b = b;
  }
  
  //同样可以简写
  //Test.fromJson(this.a, this.b);
}

1.4 、可选参数

函数有两种参数类型: required 和 optional。 required 类型参数在参数最前面, 随后是 optional 类型参数。可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。

1.4.1、命名可选参数

定义函数时,使用 {param1, param2, …} 来指定命名参数,默认都是可选如:

void enableFlags({bool bold, bool hidden}) {...}

使用 @required 注释表示参数是 required 性质的命名参数如:

 Scrollbar({Key key, @required Widget child})

1.4.2、位置可选参数

将参数放到 [] 中来标记参数是可选的如:

String say(String from, String msg, [String device]) { 
  var result = '$from says $msg';  
 if (device != null) {
     result = '$result with a $device';   
    }  
 return result;
}

String result = say('Bob', 'Howdy');

1.4.3、默认参数值

在定义方法的时候,可以使用 = 来定义可选参数的默认值。 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 null。

//命名可选参数 
void nameFlags(String name, int age,
        {bool bold = false, int height = 180}) {
      print(name + '$age' + '$bold' + '$height');
        //name18false190

    }
  nameFlags('name', 18, height: 190);

//位置可选参数
void enableFlags(String name, int age,
        [bool bold = false, int height = 180]) {
      print(name + '$age' + '$bold' + '$height');
         //pop18true180
    }

// bold 值为 true; 
    enableFlags('pop', 18, true);

1.5、抽象类用abstract关键字

  • dart抽象类主要用于定义标准, 子类可以继承抽象类,也可以实现抽象类接口
  • Dart中抽象方法不能用abstract来修饰, Dart中没有方法体的方法称为抽象方法
  • 如果子类继承抽象类,那么必须要实现抽象类里的抽象方法

抽象类用途: 抽象类主要用于约束子类 比如子类Dog中必须实现eat和run这两个方法 这个时候父类就要用abstract来修饰(定义标准)

abstract class Animal {
  eat(); // 抽象方法 因为没有方法体
  run();

  printInfo() {// 普通方法 因为有方法体
    print('我是抽象类里的一个普通方法');
  }
}

class Dog extends Animal {
  @override
  eat() {
    // TODO: implement eat
    print('小狗在吃狗粮');
  }

  @override
  run() {
    // TODO: implement run
    print('小狗在跑');
  }
}

1.6、继承

  • 用extends来继承其他类
  • 子类会继承父类里面可见的属性和方法 但是不会继承构造函数
  • 子类能复写父类的方法
  • 如果父类的默认构造函数 为有参数的构造函数 则子类必须要写自己的构造函数
  • 重写父类方法 直接和父类重名就行了或者用 @override
  • @override 可以写 也可以不写 建议写上
  • 子类里调用父类的方法 用super
class Person {
  String name = '张三';
  int age = 23;

  void getInfo() {
    // print("姓名:$name ----- 年龄:$age");
    print('姓名:${this.name}----- 年龄:${this.age}');
    // this关键字指向了当前类的实例
  }
}

子类

class Boy extends Person {
  String sex = 'man';
  // 如果父类的默认构造函数 为有参数的构造函数 则子类必须要写自己的构造函数
  Boy(String name, int age, String sex) : super(name, age) { 
  // super 表示  把子类初始化时传进来的参数 赋值给父类
     this.sex = sex;
  }

  @override  // @override 可以写 也可以不写 建议写上
  void getInfo() {
    // TODO: implement getInfo
    // super.getInfo();
    print('复写父类 ${this.name}-----${this.age}');
  } 
}

1.7、extension之扩展方法

Dart 扩展需要关键词:extension。这个关键字只有在 Dart 版本 2.7 及其以上才支持。所以请确保你工程项目中 pubspec.yaml 文件中:

environment:
sdk: ">=2.7.0 <3.0.0"

extension 的用法:

extension <extension name> on <type> {
  (<member definition>)*
}

示例:

extension StringExtension1 on String {
  //字符转换成Color对象
  toColor() {
    var hexColor = this.replaceAll("#", "");
    if (hexColor.length == 6) {
      hexColor = "FF" + hexColor;
    }
    if (hexColor.length == 8) {
      return Color(int.parse("0x$hexColor"));
    }
  }

  //字符转int
  parseInt() {
    return int.parse(this);
  }
}

extension DateTimeExtension on DateTime {
  toFormatString() {
    DateFormat dateFormat = new DateFormat("yyyy-MM-dd HH:mm:ss");
    return dateFormat.format(this);
  }
}

扩展不仅可以定义方法,还可以定义,setter,getter,operator。如果要使用这些扩展方法,只要引用导入对应的 dart 文件即可。

import 'util/extensions.dart';//导入

void main() {
  print("#90F7EC".toColor());
  print("23".parseInt());
}

1.8、接口 用关键词implements实现

Flutter是没有interface的,但是Flutter中的每个类都是一个隐式的接口,这个接口包含类里的所有成员变量,以及定义的方法。如果有一个类 A,你想让类B拥有A的API,但又不想拥有A里的实现,那么你就应该把A当做接口,类B implements 类A.

所以在Flutter中:

  1. class 就是 interface
  2. 当class被当做interface用时,class中的方法就是接口的方法,需要在子类里重新实现,在子类实现的时候要加@override
  3. 当class被当做interface用时,class中的成员变量也需要在子类里重新实现。在成员变量前加@override
  4. 实现接口可以有多个
abstract class A {
  late String name;
  printA();
}

abstract class B {
  printB(){

  }
}

class C implements A,B{
  @override
  late String name;

  @override
  printA() {
    // TODO: implement printA
    throw UnimplementedError();
  }

  @override
  printB() {
    // TODO: implement printB
    throw UnimplementedError();
  }
  
}

1.9、混合 mixins (with)

mixins的中文意思是混入,就是在类中混入其他功能。mixins是要通过非继承的方式来复用类中的代码。举个例子,有一个类A,A中有一个方法a(),还有一个类B,也想使用a()方法,而且不能用继承,那么这时候就需要用到mixins,类A就是mixins类(混入类,),类B就是要被mixins的类,对应的Dart代码如下:

void main() {
  B b = new B();
  print(b.content);
  b.a();
}

class A {
  String content = 'A Class';

  void a() {
    print("a");
  }
}

class B with A {}

输出是:

A Class
a

将类A mixins 到 B,B可以使用A的属性和方法,B就具备了A的功能,但是需要强调的是:

  1. mixins的对象是类
  2. mixins绝不是继承,也不是接口,而是一种全新的特性
  3. 可以mixins多个类

1.9.1、mixins的使用需要满足一定条件:

  1. mixins类只能继承自object
  2. mixins类不能有构造函数
  3. 一个类可以mixins多个mixins类
  4. 可以mixins多个类,不破坏Flutter的单继承

1.9.2、on关键字

on只能用于被mixins标记的类,例如mixins X on A,意思是要mixins X的话,得先接口实现或者继承A。这里A可以是类,也可以是接口,但是在mixins的时候用法有区别.

class A {
  void a() {
    print("a");
  }
}

class B {
  void b() {}
}

mixin X on A {
  void x() {
    print("x");
  }
}

// on 一个类(把A作为一个类)
// 用继承:
class mixinsX extends A with X {}

// on 的是一个接口(把A作为接口):
// 得首先实现这个接口,然后再用mix

class implA implements A {
  @override
  void a() {
    // TODO: implement a
  }
}

class mixinsX2 extends implA with X {}


//'X' can't be mixed onto 'Object' because 'Object' doesn't implement 'A'.
// class minxsBX extends B with X{
   
// }

1.10、方法冲突

如果同时存在extends, with,implements,并且它们都定义了相同的方法名,就会存在方法冲突,我们来看下面的例子:

class Extends {
  
  void log() {
    print('extends');
  }
  
}

mixin Mixins {
  
  void log() {
    print('mixin');
  }
  
}

mixin Mixins2 {
  
  void log() {
    print('mixin2');
  }
  
}

class Log extends Extends with Mixins, Mixins2 {}

void main() {
  Log().log();
}

输出结果

mixin2

再来看一下加上了implements的情况:

class Extends {
  
  void log() {
    print('extends');
  }
  
}

mixin Mixins {
  
  void log() {
    print('mixin');
  }
  
}

mixin Mixins2 {
  
  void log() {
    print('mixin2');
  }
  
}

class Implements {
  
  void log() {
    print('implements');
  }
  
}

class Log extends Extends with Mixins, Mixins2 implements Implements {}

void main() {
  Log().log();
}

输出结果为:

mixin2

这是因为在这种情况下,它识别到我们从with和extends中获得了log()方法的能力,因此调用的是Mixins2.log()。

假如我们对Implements#log方法进行实现:

class Log extends Extends with Mixins, Mixins2 implements Implements {
  
  void log() {
    print("log log");
  }
}

输出的结果为:

log log

结论:

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

推荐阅读更多精彩内容