dart语法基础

Dart语法基础之对象,接口,类以及多继承

2019-04-06  本文已影响0人  奔跑的杰尼龟zxl

Dart语言特性

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

万物皆对象

Dart是一门纯面向对象的编程语言,这意味着Dart程序在运行时所处理的值都是对象,甚至包括数字,布尔等数据。例如number int double 都是对象类型,举例而言int不主动赋值,默认是null,这就是强大的万物皆对象。

面向接口编程
类型可选 类C

在开始内容之前我们先看一个这样的例子吧

import 'dart:math';
class Point{
  var x, y;
  Point(this.x,this.y);
  operator +(p)  => new Point(x + p.x, y + p.y);

  /// get 的调用语法与变量的访问是没有区别的
  /// 实际上dart中所有变量的访问都是调用的get,每个实例变量始终有一个与之关联的get方法
  get doubleX => x * 2;

  /// 设置值
  set newY(newY){
    this.y = newY;
  }

  /// static 修饰符表明此方法不针对某个特定实例,无法访问实例变量x,y
  /// static 修饰的类方法是不会被继承的
  static distance(Point p1,Point p2){
    var dx = p1.x - p2.x;
    var dy = p1.y - p2.y;
    return sqrt(dx * dx + dy * dy);

  }
}
import 'Point.dart';
void main(){
  Point pointA = new Point(10, 10);
  Point pointB = new Point(10, 10);
  Point pointPlus = pointA + pointB;
  var x = pointPlus.x;
  var y = pointPlus.y;
  print('合并后 X = $x,Y = $y');
  var doubleX = pointPlus.doubleX;
  print('double X = $doubleX');
  pointPlus.newY = 100;
  print(pointPlus.y);
  //  合并后 X = 20,Y = 20
  //  double X = 40
  //  100
}

1.Dart中变量

1.1实例变量

当一个类声明一个实例变量时,它会确保每个实例都有自己的唯一的变量复制。对象的实例变量需要占用内存,这块内存是在对象创建时分配的。Dart会将每个新分配的变量(实例变量,局部变量,类变量和顶层变量)初始化为null。在Dart中,与其他对象一样,null也是一个对象。声明实例或者静态变量会自动引入一个get。如果变量是可变的,则一个set方法也会被自动定义。
如上,对于程序中的变量x,y,我们给予直接赋值也是可以的,
如 point.x = numberA 。dart帮我们定义好了get以及set方法,不必像java还要去针对每个变量设置get以及set方法。

1.2类变量(static变量)

一个类中只有一份类变量的副本,无论他有多少个实例,即使类没有实例,类变量也存在。类变量是延迟初始化(懒加载)的,在getter(get)第一次被调用时类变量才执行初始化,该时机在第一次尝试读取它时。默认初始化为null。

1.3 final变量

表明在初始化后就不能进行修改了。该字段有setter方法,但是没有getter方法。必须保证在任何实例方法运行前就进行初始化。
初始化的时机:

  1. 声明变量时就初始化
  2. 构造函数初始化
  3. 通过初始化列表
  4. 应当明确不能在构造函数的 { }内设置final变量的值,因为该类型变量无setter,普通变量可以
class FinalClass {
  // 1.声明赋值
  final String name = 'apple';
  final int age;
  final bool isMan;
  // 2.构造函数初始化
  FinalClass(this.age,this.isMan);
}
 /// 注意构造函数后的 : 
  final String name;
  final String doubleName;
  final int age = 18;
  HappyCat(this.name):doubleName = name+name;
1.4 相同与相等
class Girl{
  final String name;
  final int age;

  Girl(this.name, this.age);

  @override
  bool operator ==(other) {
    /// dart中类型判断 is / is!
    if(other is! Girl){
      return false;
    }
    /// 强制类型转换
    Girl otherGirl = other as Girl;
    return otherGirl.name == name && otherGirl.age == age;
  }

  // 如果2个对象相等,那么哈希码也应该相等
  @override
  int get hashCode => name.hashCode+age.hashCode;
}

  Girl girlA = new Girl('小徐', 18);
  Girl girlB = new Girl('小徐', 18);
  bool isEquals =  girlA == girlB;
  print(isEquals.toString());
  // true

2. 抽象类与接口

2.1 抽象方法与抽象类

/// 抽象类
abstract class Animal{

  final String name;

  Animal(this.name){
    print('构造函数 Animal');
  }

  /// 抽象类中可包括实例方法
  void eat(){
    print('$name 正在吃东西');

  }

  /// 抽象方法
  void hunt();
}
import 'Animal.dart';
class Tiger extends Animal{

  Tiger(String name) : super(name){
    print('构造函数 Tiger');
  }

  @override
  void hunt() {
    print('我用四肢体捕猎物');
  }
}
import 'Tiger.dart';

void main(){
  Tiger tiger = new Tiger('老虎A');
  tiger.eat();
  tiger.hunt();
}

//构造函数 Animal
//构造函数 Tiger
//老虎A 正在吃东西
//我用四肢体捕猎物

class A extends B with C 可实现类多继承

2.2 接口

接口继承使用关键字implments,但定义接口仍然使用abstract关键字

abstract class HuntAction{
 void hunt();
}

abstract class JoyAction{
 void joy();
}
import 'HuntAction.dart';
import 'JoyAction.dart';
class HappyCat implements HuntAction,JoyAction{
  final String name;
  HappyCat(this.name);

  @override
  void hunt() {
    print('$name 是通过爪子捕猎的');
  }

  @override
  void joy() {
    print('$name 喜欢和老鼠玩');
  }
}
  HappyCat happyCat = new HappyCat('小花');
  happyCat.hunt();
  happyCat.joy();
  ///小花 是通过爪子捕猎的
  ///小花 喜欢和老鼠玩

3.0 构造函数

3.1 重新向构造函数

重定向构造函数的目的是执行重定向到另外一个构造函数。在重定向构造函数中,参数列表跟在一个冒号后面,并以this.constructor(x,y,z) 指定重定向到哪个函数上。

  HappyCat(this.name):doubleName = name+name;
  
  // 重定向构造函数不能包含初始化内容
  HappyCat.NextParams(String name):this.Params(name,'参数');

  HappyCat.OneParams(String name):this(name);
  HappyCat happyCat2 =  HappyCat.NextParams('小白');
  print(happyCat2.name+" "+happyCat2.params);
  // 小白 参数
  HappyCat happyCat3 =  HappyCat.OneParams('王子');
  print(happyCat3.name);
  // 王子
3.2 工厂构造函数

通常而言,构造函数都会重新分配一份新的实例。而工厂构造函数可以达到类似于缓存的功能。
组织结构与特点:通常由factory前缀开头,它们可能没有初始化列表或初始化形式参数;它们必须又一个返回一个对象的函数体。工厂构造函数可以从缓存中返回对象,或选择分配一个新的实例。
工厂构造函数是一种构造函数,与普通构造函数不同,工厂函数不会自动生成实例,而是通过代码来决定返回的实例对象.

工厂构造函数实现单例

class FactoryObject{
  String name;
  static FactoryObject cache;

  // 私有化构造函数
  // 类名.方法 实现的是匿名的构造方法
  FactoryObject._create(this.name);

  factory FactoryObject.getInstance(String name){
    if(cache == null){
      cache = new FactoryObject._create(name);
    }
    return cache;
  }
}
  FactoryObject factoryOne = FactoryObject.getInstance('小王');
  print(factoryOne.name); // 小王
  FactoryObject factoryTwo = FactoryObject.getInstance('小白');
  print(factoryTwo.name); // 小王
  print(factoryOne == factoryTwo); // true

4. 其他

4.1 常量对象与字段

q: 何时能够创建常量对象?
先看一个错误的例子

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


  // **报错**  The constructor being called isn't a const constructor
  Point point = const Point(10, 11);

正确的例子

class Point{
  final int x , y;
  // dart语法糖,在构造方法执行前进行赋值,所以可以给final进行初始化
  const Point(this.x, this.y);
}
// 正常
Point point = const Point(10, 11);

const 表达式也是调用构造函数,但该构造函数必须是常量构造函数,而且它的常量必须是常量。并且 常量构造函数不能有函数体,他可以有一个初始化列表,前提是只计算常量。

上一篇下一篇

猜你喜欢

热点阅读