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

Dart语言特性

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

万物皆对象

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

面向接口编程
  • Dart的类型基于接口,而不是类。任意类都隐含了一个接口,能够被其他类实现
  • Dart没有final方法,允许重写几乎所有的方法
  • Dart把对象进行了抽象封装,确保所有外部操作都能通过存取方式来改变对象的状态
  • Dart 的构造函数允许对对象进行缓存,或者从子类型创建实例,因此使用构造函数并不意味着绑定一个具体的实现了
类型可选 类C
  • 类型在语法层面上是可选的
  • 类型对运行时语义没影响
  • 类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 表达式也是调用构造函数,但该构造函数必须是常量构造函数,而且它的常量必须是常量。并且 常量构造函数不能有函数体,他可以有一个初始化列表,前提是只计算常量。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容