在Java的基础上快速学习Dart语言,快速进入Flutter项目开发。
-
例1:操作符
~/ 整除
b ??= value // b为null,才进行赋值操作
person?.age = 33 // If p is non-null, set its age value to 33
print(person?.age) // person不为null时返回age值,否则返回null
String playerName(String name) => name ?? 'Guest';
等价于:
String playerName(String name) => name != null ? name : 'Guest';
instanceof 替换为 is;
as 类型转换(t as Person).name
-
例2:数据类型
num get area => pi * pow(radius, 2); // num可以用double,dart推荐使用num
int lineCount; // lineCount默认赋值null,dart中一切都是objects;
int 是一个对象类型;
int、double属于num,dart推荐使用num;
-
例3:工厂模式的两种方法
第一种:新建一个工厂类
Shape shapeFactory(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
throw 'Can\'t create $type.';
}
第二种:使用dart中关键字factory,在基类中构造函数中进行处理。
abstract class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
throw 'Can\'t create $type.';
}
num get area; // 抽象方法
}
Dart 中 Factory 构造函数作用:不用总是创建新的对象,可以返回已缓存的对象,也可以返回一个子类对象。【工厂模式】
class Logger {
final String name;
bool mute = false;
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
-
例4:Object等价于dynamic
var name = 'Bob'; // dart推荐
dynamic name = 'Bob';
String name = 'Bob';
-
例5:final与const的区别
final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
定义形式:
var a = 1;
const a = 1;
final a = 1;
int a = 1;
const int a = 1;
final int a = 1;
错误区别:
var aa = const [1, 2, 3];
final bb = [1, 2, 3];
aa=const [11, 22, 33];
//bb=const [11, 22, 33]; // 错误,bb不能修改
//aa[1]=77; // 错误,aa中的内容不能修改
bb[1]=77;
-
例6:类型转换
var one = int.parse('1'); // 可见int是个对象
var onePointOne = double.parse('1.1'); // 可见double是个对象
String oneAsString = 1.toString(); // int -> String
-
例7:函数
bool isNoble(a) { // bool可以省略;a可以不用指定类型
return a != null; // 所有函数默认返回null
}
- 可选参数 { } [ ]
{ }调用时需要加上别名
[ ]调用时是按照顺序- 默认参数
void func({bool bold = false, bool hidden = false}) {...}
-
函数可以作为参数进行传递
String scream(String str) => "num is "+str;
main() {
final values = [1, 2, 3, 5, 10, 50];
for (var length in values) {
print(scream(length));
}
}
for循环代替为:
values.map(scream).forEach(print);
values.skip(1).take(3).map(scream).forEach(print); // skip从0开始
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
list.forEach(printElement);
-
匿名函数
var list = ['apples', 'bananas', 'oranges'];
list.forEach(**(item)** { // 构建匿名函数
print('\${list.indexOf(item)}: \$item');
});
var loudify = (msg) => '!!!\ ${msg.toUpperCase()} !!!'; // 构建匿名函数
print(loudify('hello'));
-
函数嵌套
makeAdder(num addBy) {
return (num i) => addBy + i; // 返回一个匿名函数
}
void main() {
var add4 = makeAdder(4);
print(makeAdder(2)(3) == 5);
print(add4(3) == 7);
}
-
例8:类
dart支持抽象类;并且可以在一个文件中定义多个类。
class Bicycle {
int cadence;
int _speed; // 下划线表示私有
int get speed => _speed; // get方法
int gear;
Bicycle(this.cadence, this.speed, this.gear); // 简化构造函数,不要忘记尾部分号
// 单引号,双引号一样;''' '''输出多行;var s = r'C://a/b/'(r表示raw)
// ${expression} 表达式
// $variableName 标识符
// => 一行函数或方法
@override
String toString() => 'Bicycle: $speed mph';
// 不能写return getGear() => return gear;
getGear() => gear;
}
void main() {
// 可以省略new
var bike = new Bicycle(2, 0, 1);
print(bike); // Instance of 'Bicycle'
}
-
constant constructors
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1); // a b are the same instance
var c = ImmutablePoint(1, 1); // a c are not the same instance
const构造函数得到的类不能够再改变。
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
-
Named constructor
class Point {
num x, y;
Point(this.x, this.y); // 构造函数:Dart has syntactic sugar to make it easy
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
-
Named constructor 手动调用父类有参构造函数
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
} // Warning: The right-hand side of an initializer does not have access to this.
main() {
var emp = new Employee.fromJson({});
if (emp is Person) {
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
Warning: The right-hand side of an initializer does not have access to this.
-
Named constructor 使用已有构造函数
class Point {
num x, y;
Point(this.x, this.y);
Point.alongXAxis(num x) : this(x, 0); // // 不能访问this属性,但可以调用已有构造函数
}
-
get set方法的简化
class Rectangle {
num left, top, width, 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;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12; // 调用set right方法
assert(rect.left == -8);
}
-
implements
Dart中有抽象类,关键字:abstract。
dart没有interface关键字,因为所有的类都定义成了interface,类都是隐式接口。
隐式的接口:每一个类都隐式的定义一个接口,这个接口包含了这个类的所有实例成员和它实现的所有接口。如果相应创建一个类A, 这个类A 支持类B 提供的API函数,但是不继承B 的实现,则类A 需要实现类B 的接口。
class Imposter implements Person, PersonB {
// Person是一个类,实现Person类的所有属性成员和方法。
// 可以“多实现”
}
-
例9:重载操作符
Dart可以重载操作符【!=不可以进行重载;若重载了==,必须同时重载hashCode】
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector **operator** +(Vector v) => Vector(x + v.x, y + v.y);
Vector **operator** -(Vector v) => Vector(x - v.x, y - v.y);
}
-
例10:枚举
每个枚举类型都用于一个index的getter,用来标记元素的元素位置。第一个枚举元素的标是0 。
enum Color { red, green, blue }
assert(Color.red.index == 0);
assert(Color.blue.index == 2);
values获取所有枚举值:
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
-
例11:mixins混合类型使用关键字with
Mixins不是一种在经典意义上获得多重继承的方法。Mixins是一种抽象和重用一系列操作和状态的方法。它类似于扩展类所获得的重用,但它与单继承兼容,因为它是线性的。
class T = A with S; // A中的方法为A和S方法的集合,如果有重复,取S中的。
class T = B with A, S 等价于 class T = (B with A) with S;
注:使用Mixin时必须继承至Object,并且不能调用super()方法。
mixins比较陌生,也比较重要。详细资料参考:
https://juejin.im/post/5bb204d3e51d450e4f38e2f6
-
例12:泛型
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
'index.html': 'Homepage',
};
print(names is List<String>); // true
由于Java在运行时会删除掉泛型,所以在Java中只能判读names是否为List,而不能判断是否为List<String>。
var views = Map<int, View>(); // int也是对象
class Foo<T extends SomeBaseClass> { }
泛型方法:T first<T>(List<T> ts) {
-
例13:Cascade ..
Cascade notation (..) Dart 支持使用两个点号(..)进行级联调用(cascade operator),级联调用和普通方法调用一样,但是它并不返回方法的返回值,而是返回调用对象自身,这样你就可以连续调用同一个对象上的多个方法了。
Cascade ..例子:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
等价于:
querySelector('#confirm') // Get an object 没有分号
..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
-
例14:异常Exception和Error
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
**rethrow;**
} catch (e, s) {
// No specified type, handles all
print('Something really unknown: $e');
}
-
例15:import
import 'package:lib2/lib2.dart' **as** lib2;
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
// To lazily load a library 延迟加载
import 'package:greetings/hello.dart' **deferred as** hello;
-
例16:异步
Future greet() async { // 必须返回Future,必须有async,await
await hello.loadLibrary();
hello.printGreeting();
}
Future<String> lookUpVersion() async => '1.0.0'; // dart会自动添加await
返回Future时,dart会自定添加为:Future<void>;
处理流数据使用await for.
-
例17:生成器 yield
-
同步生成器:使用sync*和yield
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
-
异步成器:使用async*和yield
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
-
递归生成器 使用yield*
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
-
例18:Typedefs定义函数
dart中函数也是对象,使用Typedefs定义函数类型。
typedef Compare = int Function(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function); // OK
assert(coll.compare is Compare); // OK
}
-
例19:元数据@
library todo;
class Todo {
final String who;
final String what;
const Todo(this.who, this.what);
}
使用:
@Todo('seth', 'make this do something')
void doSomething() {
print('do something');
}
-
例20:其它
Map中的key和value支持任何数据类型:
Maps:Both keys and values can be any type of object
var gifts = {
'first': 'partridge',
10: 'neon', // key可以为num类型
};
main()入口的两种表达方式:
void main() { }
void main(List<String> arguments) { } // 命令行执行携带参数
运行时类型获取 runtimeType:
print('The type of a is ${a.runtimeType}');
assert的一个使用场景:
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
-
总结
该文章只是参考Dart官网文档,在Java的基础上,简单的介绍了一下Dart基本语法。以后会对Dart Library进行一些实用性的介绍。
网友评论