美文网首页
Learn Dart Based on Java

Learn Dart Based on Java

作者: 奋飞的蜗牛ing | 来源:发表于2018-10-26 20:47 被阅读113次

在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进行一些实用性的介绍。

相关文章

网友评论

      本文标题:Learn Dart Based on Java

      本文链接:https://www.haomeiwen.com/subject/jezqtqtx.html