Dart学习

chapter1 :简介

Dart是纯面向对象、基于类、使用可选类型、支持混入式继承以及Actor模式的并发编程语言。

1.关注对象的行为而非他的内部实现:
	(1) Dart 的类型基于接口,而不是类. 作为一项原则,任意 类 都隐含了一个接口,能够被其它类实现.不管其他类是否使用了同样底层的实现
	(2) Dart 没有final方法,部分内置的操作符除外.
	(3) Dart 把对象进行了抽象封装, 以确保所有外部操作都通过存取方法来改变对象的状态.
	(4) Dart 的构造函数允许对对象进行缓存,或者从子类型创建实例,因此使用构造函数并不意味着绑定了一个具体的实现.

Dart中的整数没有32位或64位可代表的最大值的限制,唯一能够限制其大小的是可用内存的大小.
但部分情况除外,比如:
	👍在dart编译为javascript的时候,所有的数字都会变成javascript的数字,而js中只含有数字类型,并无整数类型,即使用浮点数来表示整数,并有大小的限制.
初见Dart语法糖
  1. 我们先来看一下一个class
	// 这是一个叫Point的Class
	class Point{	
		var x, y;
		// 形参 a, b 将会接受具体实参的值
		// 此后 a, b 的值将会被赋值给 Point 中的x, y
		Point(a, b) {
			x = a;
			y = b;
		}
	}

Point 是一个最基础的类, 他有两个实例变量(或字段) : x与y.
要创建一个Point 类 的 实例 , 我们可以使用 new 表达式 来调用他的构造函数.

变量x, y 的值是由构造函数的实际参数来设置,而构造函数是由 new 调用的.
Dart 为此提供了一种特殊的语法糖:

	class  Point{
		var x , y;
		Point(this.x, this.y)
	}

👍 this的指向其实很容易理解, 此时此刻是谁在调用,那么this指向的就是谁.
于是此处的this.x 自然也很好区分赋值给谁了.

注意: 在我们需要使用到某一些库的时候,需要先 import 其.

👍 Dart代码用库作为模块化的基本单元.每一个库都定义了一个命名空间,此命名空间包含所有在库中声明的实体的名称,其他库的实体也可以被导入进来.而Dart 核心库 中也声明了一些实体, 这些实体都已经被隐含地导入到所有的Dart库中了.

EG: 我们现在需要导入一个并不在核心库中的实体 — sqrt() ,它属于math库,请看:

	// 与上述point类有关, 初学不明白具体意思,日后填坑
	library points;
	// 在这里盗入 math 库,就像python
	import 'dart:math';
	class Point{
		var x , y;
		Point(this.x , this.y);
		static distance(p1 , p2){
		// 在这里就可以正确使用 math 库 中的实体sqrt()了
			return sqrt( 3 * 3  + 4 * 4);
		}
	}

于是我们自己申明的point库, 现在就可以正常使用sqrt()了,任意其他库,在成功导入Point库 后,也可以使用我们定义的 point类.

👍👍 import 后面跟着的是一个字符串’dart:math’.导入指向的都是用字符串表示的统一资源标至符(URI),编译器会通过指定的URI去找对应的库.
👍需要注意的点:

  1. 上面的demo中,我们看到了static,他表示Dart中的静态成员
  2. static 关键字用来实现类级别的变量和函数
  3. 静态方法不能访问非静态成员,非静态方法可以访问静态成员

chapter2 :对象、接口、类与mixin

一、属性访问器( )函数setter和getter

在Dart类的属性中有一种为了方便访问它的值特殊函数,那就是setter,getter属性访问器函数。实际上,在dart中每个实例属性始终有与之对应的setter,getter函数(若是final修饰只读属性只有getter函数, 而可变属性则有setter,getter两种函数)。而在给实例属性赋值或获取值时,实际上内部都是对setter和getter函数的调用。

1、属性访问器函数setter

setter函数名前面添加前缀set, 并只接收一个参数。
setter调用语法于传统的变量赋值是一样的。
如果一个实例属性是可变的,那么一个setter属性访问器函数就会为它自动定义,所有实例属性的赋值实际上都是对setter函数的调用。

👍get 有点类似于计算属性,其对一个属性进行操作;
👍set 亦是对 属性进行操作,但在为其赋值的时候,却没有使用圆括号进行传参,而是直接使用等号进行赋值。

class Rectangle {
  num left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);
  set right(num value) => left = value - width;//使用set作为前缀,只接收一个参数value
  set bottom(num value) => top = value - height;//使用set作为前缀,只接收一个参数value
  get square => left * top ;
}

main() {
  var rect = Rectangle(3, 4, 20, 15);
  rect.right = 15;//调用setter函数时,可以直接使用类似属性赋值方式调用right函数。
  rect.bottom = 12;//调用setter函数时,可以直接使用类似属性赋值方式调用bottom函数。
  print(rect.square); 
}

2.8 接口
Dart中没有接口的存在,因为其不是必要的,我们可以通过定义一个抽象类来描述所需的接口。

	abstract class CartesianPoint{
		get x;
		get y;
	}
	abstract class PolarPoint{
		get rho;
		get theta;
	}
	// 尽管没有了接口声明, 泪也可以使他的实例实现特定的接口
	class Point implements CartesianPoint , PolarPoint{
		// 这里是Point 类的实现代码
	}

上述代码 Point 类并不是 CartesianPoint 的子类,他没有继承CartesianPoint (或者 PolarPoint )的任何成员。implements的目的是在接口间建立预期的关联, 而不是实现共享实现。
我们可以使用 is 检查对象的类是否明确地实现了某个接口(直接或间接)

	5 is int; // true
	'abc' is string; // true
	10 is string; //false
	Point.toString() is String; // true
	Point is CartesianPoint; // true  

2.10 noSuchMethod()

Dart 中的计算都是围绕对象方法的调用。如果调用了一个不存在的方法,则默认的行为会抛出一个noSuchMethodError 错误,但是并非总是如此
当调用一个实例中不存在的方法时,Dart运行时会调用当前对象的noSuchMethod()方法。因为Object类noSuchMethod()方法的实现就是抛出noSuchMethodError错误,所以我们通常会看到这个熟悉的行为。但是优点在于,noSuchMethod()方法可以被重写。

class Proxy{
	final forwardee;
	Proxy(this.forwardee);
	noSuchMethod(inv){
		return runMethod(forwardee,inv);
	}
}

注意:

noSuchMethod() 的参数是 Invocation类的一个实例,他是定义在核心库中的一个特殊类型,用于描述方法的调用。一个Invocation反映了原始的调用,描述了我们是原图调用方法的名称、传递的参数以及一些其他细节。

2.11 常量对象与字段

常量的值可以提前计算,只需一次,无需重新计算。Dart中常量是规范化的,一个给定的值只会产生一份常量。

const与final

我们一般对于常量使用 const 与 final 定义;
两者的差别在于: const 需要立即对对象进行初始化,而final可以延后初始化(可能表达的意思有误)。 
因为时常会出现这种情况: 我们需要用到形参里的数据进行运算,这个数据一定是一个常量,但我们并不清楚他具体的值,在这种情况下使用const就不可取了,因为const是需要立即初始化的,于是final就可以在此处被我们使用。

2.12 类方法


2.15 mixin
在Dart 中是没有多继承的,我们如果想实现类似多继承的需求,可以使用mixin(他并不是多继承,仅仅是帮我们实现了这个功能)。下面记录的是Dart2.x版本的 mixin 功能。

  1. 作为mixin的类只能继承自Object,不可以继承自其他类。
  2. 作为mixin的类 不能拥有构造函数
  3. 一个类可以mixin多个类,若多个类中有同名函数,则后mixin类的函数会覆盖前面的同名函数
  4. mixin 不是继承也不是接口,而是一种新的特性。
class Mixa {
  String strA = "我是A的string";
  void funA() {
    print("被mixin的类只能继承自Object");
    print("被mixin的类不能拥有构造函数");
  }
}

class Mixb {
  String strB = "我是B的string";
}

class MixExted extends Mixa {
  MixExted(String name) {
    print('被 mixin 的类无法拥有构造函数,但被 extends 的类可以');
    print(name);
  }
  void MixExtedPrint() {
    print("继承自Mixa的MixExted方法");
  }
}

class mixC extends MixExted with Mixa, Mixb {
  mixC(String name) : super(name);
}

void main() {
  mixC mixc = mixC('我是mixC');
  print(mixc.strA);
  print(mixc.strB);
  mixc.MixExtedPrint();
}

常用的APi 总结

数字篇 ( num类型 )

	void main() {
		//	parse();
		//  用于将字符串类型转换成num类型,不会修改源数据
		//	如果传递除数字以外的任何值,则解析函数抛出 FormatException  如: '12Aaa'
		 print(num.parse('12') + 15); // 27
		 print(num.parse('10.91')); // 10.91
		
		 int n = 880;
		 print(n.hashCode); // 输出数字的哈希值
		 print(n.isFinite); // 如果数字不是NaN或正无穷大或负无穷大,则该属性返回布尔值true。
		 print(n.isNegative); // 若数字为负数,即可返回true
		 print(n.sign); // 数字为负数 则返回-1;数字为 0 ,则返回 0;数字正数,则返回1
		 print(n.isEven); // 数字为偶数,返回true
		 print(n.isOdd); // 数字为奇数,返回true
		 print(n.abs()); // 返回数字绝对值
		 print(n.ceil()); // 针对小数执行, 返回该数的上一个整数 ; [注意分辨n的正负,-1.2 返回的是-1;1.2  返回的是2]
		 print(n.compareTo(12)); // 0:值相等。 n > 比较值 返回 :1。n < 比较值 返回 -1
		
	 	 num a = 5.97777;
 		 print(a.toInt()); // 取整(不进行四舍五入)
		 print(a.toString().runtimeType); // 不修改源数据
		 print(a.truncate()); // 返回不带小数点的 整型
	}

字符串篇 ( String类型 )

	void main(List<String> args) {
	  String str = ' hello ';
	  print(str.isEmpty); // 判断字符串长度是否为0,是则返回true,否则为false
	  print(str.length); // 返回长度
	  print(str.toLowerCase()); // 转为小写
	  print(str.toUpperCase()); // 转为大写
	  print(str.trim()); // 去除左右所有空格
	  print(str.compareTo('haiho'));
	  // 返回表示两个字符串之间关系的整数。
	  //字符串相等返回 0。
	  //当第一个字符串大于第二个字符串时 返回1
	  //当第一个字符串小于第二个字符串时 返回-1
	  print(str.replaceAll('ll', 'cc')); // 用给定值替换与指定模式匹配的所有子字符串
	  print(str.split('l')); // 在指定分隔符的匹配处拆分字符串并返回子字符串列表。
	  print(str.substring(3)); //  根据索引值,返回一个字符串 (3)=> (0,3) 与js一样
	  int a = 5;
	  print(a.toString()); // 返回对象的字符串表示形式
	  print(str.codeUnitAt(0));// 返回给定索引处的16位UTF-16代码单元。
	}

列表篇 ( List类型 )

	void main(List<String> args) {
	  List<int> lst = [10, 20, 25, 19];
	  lst.add(123);
	  print(lst);
	  lst.replaceRange(0, 3, [11, 23, 24]);
	  // 将lst列表的前三项 分别替换为: 11,23,24
	  print(lst.first); // 此属性返回列表中的第一个元素
	  print(lst.last); // 此属性返回列表中的最后一个元素
	  print(lst.isEmpty); // 判断是否为空
	  print(lst.length); // 打印列表长度
	  print(lst.reversed); // 反转列表
	  // print(lst.single); //检查列表是否只有一个元素并返回它 否则报错
	  lst.remove(10); // print(lst); // remove()函数删除列表中第一次出现的指定项
	  print(lst.removeLast()); // 移除列表的最后一个数据,操作将修改源数据
	  print(lst);
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值