Dart基础(四)

级别: ★☆☆☆☆
标签:「Flutter 」「Dart」「Dart class」「Dart mixin」「Dart override」
做者: WYW
审校: QiShare团队php


前言
笔者在以前已经写了3篇Dart的基础文章了。
Dart 基础 (一)
Dart 基础 (二)
Dart 基础 (三)git

笔者在本文中主要会分享:类、实例变量、构造方法、命名构造方法、实例方法、静态变量、静态方法、set、get 方法、extendsimplementsmixinabstractoverride相关的内容。github

1.类

下边笔者先以Point 类为例,分享下关于实例变量构造方法命名构造方法实例方法静态方法静态变量set get方法 的内容。算法

Dart 是一种面向对象的编程语言,同时支持基于 mixin 的继承机制。mixin相关的内容会在下文解释。每一个对象都是一个类的实例,全部的类都继承于 Object。 基于 Mixin 的继承 意味着每一个类(Object 除外) 都只有一个超类,一个类的代码能够在其余 多个类继承中重复使用。express

使用 new 关键字和构造方法来建立新的对象。 构造方法名字能够为 ClassName 或者 ClassName.identifier。 在Dart2.0的时候,建立新的对象的时候,new 关键字是可选的。当前Dart最新版本是2.4.0,2019-06-27 Dart开发团队发布2.4.0版本Dart。 Dart change log编程

1.1 实例变量json

class Point {
  
  // 实例变量
  num x;
  num y;
}
复制代码

1.2 构造方法:构造方法 定义一个和类名同样的方法数组

// 构造方法 定义一个和类名同样的方法
  Point(num x, num y) {
    // this 关键字指当前的实例
    this.x = x;
    this.y = y;
  }
  
  // 因为把构造方法参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操做
  // Point(this.x, this.y);
复制代码

1.3 命名构造方法bash

// 命名构造方法
  Point.fromJson(Map json) {
    // 只有当名字冲突的时候才使用 this。不然的话, Dart 代码风格样式推荐忽略 this。
    x = json['x'];
    y = json['y'];
  }

  Point.namedConstructor(Map json){
    x = json['x'];
    y = json['y'];
  }

复制代码

命名构造方法使用场景有:模型类中解析数据场景。微信

举个简单例子:如返回一个列表数据的状况,返回数据多是是一个包着多个字典的数组,那么,处理相应数据的时候,须要对数据进行相应的解析。解析的过程就可能用到命名构造方法。把一个个字典当作实例,提取出来。

[
	{
		"name":"QiShare1",
		"age":"1"
	},
	{
		"name":"QiShare2",
		"age":"1"
	},
	{
		"name":"QiShare3",
		"age":"1"
	},
	{
		"name":"QiShare4",
		"age":"1"
	},
	{
		"name":"QiShare5",
		"age":"1"
	},
	{
		"name":"QiShare6",
		"age":"1"
	},
	{
		"name":"QiShare7",
		"age":"1"
	},
]
复制代码

1.4 实例方法

// 实例方法
  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx*dx + dy*dy);
  }
复制代码

1.5 静态方法

使用static关键字修饰的方法为静态方法,至关于类方法。使用类名能够直接调用。

// 静态方法
  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
复制代码
void classDemo() {

    var jsonData = jsonDecode('{"x":2, "y":2}');
    // Create a Point using Point().
    var p1 = new Point(1, 1);
    print('p1点x坐标:${p1.x}');
    print('p1点y坐标:${p1.y}');

    // Create a Point using Point.fromJson().
    var p2 = new Point.fromJson(jsonData);
    print('p2点x坐标:${p2.x}');
    print('p2点y坐标:${p2.y}');

    num distance = p2.distanceTo(p1);
    print('p1到p2的距离: $distance');

    Map jsonData3 = {
      'x': 3,
      'y': 3,
    };

    Point p3 = Point.namedConstructor(jsonData3);
    print('p3点x坐标:${p3.x}');
    print('p3点y坐标:${p3.y}');
    
    num distance12 = Point.distanceBetween(p1, p2);
    print('p1和p2之间的距离 $distance12');
    
    }
    
复制代码

输出内容

flutter: p1点x坐标:1
flutter: p1点y坐标:1
flutter: p2点x坐标:2
flutter: p2点y坐标:2
flutter: p1到p2的距离: 1.4142135623730951
flutter: p3点x坐标:3
flutter: p3点y坐标:3
flutter: p1和p2之间的距离 1.4142135623730951

复制代码

1.6 静态变量

静态变量对于类级别的状态是很是有用的,笔者对这句话的理解是:静态变量能够由类名直接调用。

class Color {
  static const red =
      const Color('red'); // A constant static variable.
  final String name;      // An instance variable.
  const Color(this.name); // A constant constructor.
}
复制代码

使用方式

String colorName = Color.red.name;
    print('colorName:$colorName');
复制代码

输出内容

colorName:red`
复制代码

1.7 set get 方法

下边笔者举了一个类Rectangle的left、top、width、height的Set、Get方法的例子。

class Rectangle {
  num left;
  num top;
  num width;
  num 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;
}

复制代码

使用方式

Rectangle rectangel = Rectangle(0, 0, 375, 667);
    print('rectangel.left:');
    print(rectangel.left);
    print('rectangel.right:');
    print(rectangel.right);
    print('rectangel.width:');
    print(rectangel.width);
    print('rectangel.height:');
    print(rectangel.height);
    print('rectangel.right:');
    print(rectangel.right);
    print('rectangel.bottom:');
    print(rectangel.bottom);

复制代码

输出结果:

flutter: rectangel.left:
flutter: 0
flutter: rectangel.right:
flutter: 375
flutter: rectangel.width:
flutter: 375
flutter: rectangel.height:
flutter: 667
flutter: rectangel.right:
flutter: 375
flutter: rectangel.bottom:
flutter: 667
复制代码

2. extends 与 implements

extends

关键字extends 用于继承父类的实例变量及方法等。Dart 只支持单继承。

implements

Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. If you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B interface.

每一个类都隐式地声明了一个包含全部的实例变量和类已经实现的接口。
若是你想建立一个类A,没有继承类B,可是类A可访问类B的API,那么类A 应该实现类B的接口。
上边的内容,结合着下边的例子,笔者的理解是:Chicken隐式地声明了Animal 的实例变量,和类Animal 已经实现的方法。Chicken支持在没有继承类Animal的状况下,可访问类B的API。
一个类能够implements 多个类的API,因此implements算是一种变向实现多继承的方式。

class Animal {
  String name;
  void ability() {
    print('Animal 的能力');
  }
}

class Bird extends Animal {
  void ability(){
    print('bird can fly');
  }
}

class Fish extends Animal {
  void ability(){
    print('fish can swim');
  }
}

class Dog extends Animal {
  void ability(){
    print('dog can bark');
  }
}

class Chicken implements Animal {
  String name;
  void ability() {
    print('chicken can lay eggs');
  }
}

复制代码

调用如上代码的方式及相应输出结果以下:

Dog dog = Dog();
    dog.ability();
    Fish fish = Fish();
    fish.ability();
    Bird bird = Bird();
    bird.ability();
    Chicken chicken = Chicken();
    chicken.ability();
    
    

// 输出结果:
flutter: dog can bark
flutter: fish can swim
flutter: bird can fly
flutter: chicken can lay eggs
复制代码

3. mixin

Mixins 是一种在多类继承中重用一个类代码的方法。笔者的理解是,mixin至关因而一个工具类,使用 with 关键字使用了mixin的类,就能够使用mixin中的代码。

Mixins are a way of reusing a class’s code in multiple class hierarchies.

To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use mixins:

Mixin 是一种在多个类中重用某些代码的方式。 使用mixin ,需使用 with 关键字,with后边跟mixin的名,with 后边能够跟多个mixin名字,及能够同时使用多个mixin中的代码。下边笔者举了一个开发者学习基础语言的例子。

笔者定义了一个Developer的mixin,若是是iOS 开发者须要先学习C语言基础,若是是Android 开发者,须要先学习Java语言,若是是Flutter 开发者,须要先学习Dart 语言。

mixin Developer {
    bool isIOS = false;
    bool isAndroid = false;
    bool isFlutter = false;
    
    // 须要学习的基础语言
    void needLearnBaseProgram () {
      if (isIOS) {
        print('Need Learn C Firstly');
      } else if (isAndroid) {
        print('Need Learn Java Firstly');
      } else if (isFlutter) {
        print('Need Learn Dart Firstly');
      } else {
        print('May be need Learn Other Language');
      }
    }
    
  }

class FlutterDeveloper with Developer {
	String name;
	FlutterDeveloper(String name) {
		isFlutter = true;
		this.name = name;
	}
}
  
复制代码

使用的相关代码:

FlutterDeveloper flutterDeveloper = FlutterDeveloper('FlutterEnginerName');
    flutterDeveloper.needLearnBaseProgram();
    
    // 输出结果: flutter: Need Learn Dart Firstly
复制代码

注意事项: 当在if else 场景下使用 bool 类型变量的时候,须要注意bool变量是否赋值过了,不然会有相似以下的异常信息。

flutter: The following assertion was thrown while handling a gesture:
flutter: Failed assertion: boolean expression must not be null
复制代码

4. abstract

使用 abstract 修饰的类 记为抽象类。抽象类用于定义接口 及部分实现。

笔者举了以下例子:

建立了People 类,而且声明了 String skinColor();的抽象方法,建立并实现了 void ability() 方法;

abstract class People {
  String skinColor();
  void ability() {
    print('All can Communicate');
  }

}

class YellowPeople extends People {
  @override
  String skinColor() {
    String color = 'Yellow';
    print(color);
    return color;
  }
}

class BlackPeople extends People {
  @override
    skinColor() {
      String color = 'black';
      print(color);
      return color;
    }
}

class WhitePeople extends People {
@override
  skinColor() {
    String color = 'White';
    print(color);
    return color;
  }
}
复制代码

下边是使用示例,及相应的输出结果。

YellowPeople yellowPeople = YellowPeople();
yellowPeople.ability();
yellowPeople.skinColor();

WhitePeople whitePeople = WhitePeople();
whitePeople.ability();
whitePeople.skinColor();

BlackPeople blackPeople = BlackPeople();
blackPeople.ability();
blackPeople.skinColor();
    
// 输出结果:
flutter: All can Communicate
flutter: Yellow
flutter: All can Communicate
flutter: White
flutter: All can Communicate
flutter: black

复制代码
  • 抽象类不能建立实例。
  • 抽象方法为没有方法体的方法。只有抽象类中能够写抽象方法,其余普通类不能够。
    • 例:若是BlackPeople的skinColor 没有方法体即没有实现,则会报错以下:'skinColor' must have a method body because 'BlackPeople' isn't abstract. Try making 'BlackPeople' abstract, or adding a body to 'skinColor'.
  • 继承了抽象类的子类必须实现抽象方法
    • 以WhitePeople 为例,若是不实现skinColor 方法会报出以下错误:
      • Missing concrete implementation of People.skinColor.
      • Try implementing the missing method, or make the class abstract.

5. override

"5.1 override 运算符"及override toString

这里笔者对override 运算符添加了引号。至于缘由,等你们看完了下边的内容以后,便会了解笔者的用意。下文提到的override和重写是一个意思。

先看下运算符重写的示例代码:

Vector 类,重写了+ 运算符和减运算符,以达到Vector能够直接进行加减的目的。笔者还重写了Vector类的toString 方法,便于查看Vector的x、y值。

class Vector {
  final int x;
  final int y;
  
  const Vector(this.x, this.y);

  Vector operator +(Vector v) {
    return Vector(x + v.x, y + v.y);
  }

  Vector operator -(Vector v) {
    return Vector(x - v.x, y - v.y);
  }
  
  @override
  String toString() {
    return 'runtimeType:' + this.runtimeType.toString() + ',x:' + x.toString() +',y:' + y.toString();
  }
  
}

复制代码

使用Vector的+、-运算符,及重写toString后,使用Vector的示例代码及输出结果以下:

Vector v1 = Vector(1, 1);
    Vector v2 = Vector(2, 2);
    Vector v3 = v1 + v2;
    Vector v0 = v2 - v1;
    print(v0);
    print(v3);

// 输出结果: 
flutter: runtimeType:Vector,x:1,y:1
flutter: runtimeType:Vector,x:3,y:3

复制代码

重写toString的效果是:可控制print的对象的内容及格式。 这一点便于非调试环境下查看一些具体错误信息。

上文笔者提到了重写运算符是加引号的缘由以下:在笔者看来,运算符的重写有点跑题了。重写toString才算是重写。重写的toString的返回值、方法名和参数和父类Object都同样。如你们有不一样理解,欢迎讨论。

参考学习网址


小编微信:可加并拉入《QiShare技术交流群》。

关注咱们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
Dart基础(一)
Dart基础(二)
Dart基础(三)
iOS 短信验证码倒计时按钮
iOS 环境变量配置
iOS 中处理定时任务的经常使用方法
算法小专栏:贪心算法
iOS 快速实现分页界面的搭建
iOS 中的界面旋转
奇舞周刊

相关文章
相关标签/搜索