Dart2 class & object

Dart2 类与对象

类和对象

  • class 关键字声明一个类

  • 创建对象 使用 new + 构造函数()

  • 所有的对象都是继承Object,属基类

创建一个类

void main() {
  Rcperson p1 = Rcperson();
  p1.name = 'roc';
  p1.age = 8888;
  p1.run();
  
  var p2 = Rcperson();
  p2.name = 'cor';
  p2.age = 6666;
  p2.run();
}
class Rcperson {
  String? name;
  num? age;
  void run(){
    print('name:$name age:$age');
  }
}

name:roc age:8888
name:cor age:6666

dart中同一个作用域内不能有两个同名方法,方法名称是寻找方法实现的唯一标识

创建一个 Dart file 内部定义一个Person类

class Person {
  String? name;
  num? age;
  void run(){
    print('name:$name age:$age');
  }
}

  • 在main.dart中 导入 的新创建的dart file 的头部信息,就可以使用了
// 导入头部信息
import 'roc_test_demo.dart';

Person p3 = Person();
  p3.name = '大牛';
  p3.age = 2222;
  p3.run();

// 打印 name:大牛 age:2222
  • _ 下划线内部成员的构建(私有化),外部不能直接访问,同一个文件中可以访问
    _ 下划线成员变量的作用域是当前文件的内部的,外部文件不能访问,即文件私有化
class Student{
  String? _name;
  num? _age;
  void _run(){
    _name = '飞机';
    _age = 18;
    print('name:$_name age:$_age');
  }
  void getContent(){
    _run();
  }
}

Student s1 = Student();
  s1.getContent();

name:飞机 age:18
  • 自定义类的构造函数(一般使用默认的构造函数)
    • 一旦自定义类构造函数,默认的构造函数就不起作用了
class Arsenal1{
  String? _name;
  num? _price;

  // 添加构造函数
  Arsenal1(String name,int price){
    _name = name;
    _price = price;
  }
  void _run(){
    print('name:$_name price:$_price');
  }
  void getContent(){
    _run();
  }
}

class Arsenal1{
  String? _name;
  num? _price;

  // 添加构造函数 推荐使用
  Arsenal1(this._name,this._price);

  void _run(){
    print('name:$_name price:$_price');
  }
  void getContent(){
    _run();
  }
}


Arsenal1 a1 = Arsenal1('导弹', 40000);
  a1.getContent();

name:导弹 price:40000
  • 自定义命名构造函数
class Arsenal1{
  String? _name;
  num? _price;

  // 自定义命名构造函数
  Arsenal1.withName(this._name,this._price);

  void _run(){
    print('name:$_name price:$_price');
  }
  void getContent(){
    _run();
  }
}

Arsenal1 a2 = Arsenal1.withName('巡逻舰', 100000);
a2.getContent();

name:巡逻舰 price:100000
  • 常量对象
    当对象的成员属性都是final修饰,这个对象可以被创建为常量对象,使用const修饰构造函数
// 常量对象
class Rcperson2{
  final String name;
  final num age;
  const Rcperson2.withName(this.name,this.age);
  void run(){
    print('name:$name age:$age');
  }
}

// 常量对象 初始化之后不能做任何的修改
  Rcperson2 constP = Rcperson2.withName('CJL', 2);
  constP.run();

工厂构造 & 单例对象

  • 工厂构造

    • 创建一个 dart file ,命名为 factory_test_demo.dart
    • 构造函数是不能添加return的,factory修饰的工厂方法除外
  • 单例对象

  • 构建单例对象的方法名必须与当前对象的类名一样,不能和OC或swift一样写个sharedInstance.

  • 方式一

class Factory1{
  static Factory1? _instance;
  // 创建私有的构造函数,将默认的构造函数私有化
  Factory1._init();
  // 单例的方法名同类名
  factory Factory1(){
    if (_instance == null){
      _instance = Factory1._init();
    }
    return _instance!;
  }
}

// 单例对象
  Factory1 f1 = Factory1();
  Factory1 f2 = Factory1();
  print(f1 == f2); // true
  • 方式二
class Factory2{
  static Factory2? _instance;
  // 创建私有的构造函数,将默认的构造函数私有化
  Factory2._init();
  // 单例的方法名同类名
  factory Factory2(){

    return _instance ??= Factory2._init();
  }
}

// 单例对象
  Factory1 f1 = Factory1();
  Factory1 f2 = Factory1();
  print(f1 == f2); // true
  • 方式三 推荐使用
class Factory3{
  static Factory3? _instance;
  // 创建私有的构造函数,将默认的构造函数私有化
  Factory3._init();
  // 单例的方法名同类名
  factory Factory3() => _instance ??= Factory3._init();
}

// 单例对象
  Factory1 f1 = Factory1();
  Factory1 f2 = Factory1();
  print(f1 == f2); // true
  • 初始化列表 冒号后面是初始化列表

方式一

class InitializetionList{
  String name;
  num age;
  final _h;
  // 创建初始化列表
  InitializetionList(this.name,this.age,num h):_h = h,assert(h>170); 
}

  // 初始化对象
  InitializetionList ill = InitializetionList('roc', 18, 180);

方式二 推荐使用 先校验 再赋值

class InitializetionList2{
  String name;
  num age;
  final _h;
  // 创建初始化列表
  InitializetionList2(this.name,this.age,num h):
        _h = h,
        assert(h>170),
        assert(age>=18){
    print('name:$name age:$age height:$_h');
  }
}
// 初始化对象
InitializetionList2 ill2 = InitializetionList2('roc', 18, 180);

// name:roc age:18 height:180

方式三 推荐使用 先校验 再赋值

class InitializetionList3{
  String _name;
  num _age;
  num _h;
  InitializetionList3(String name,num age,num height):
        _name = name,
        _age = age,
        _h = height,
        assert(name != null && age >= 18 && height >= 170) {
    print('name:$_name age:$_age height:$_h');
  }
}

InitializetionList3 ill3 = InitializetionList3('roc', 18, 190);

// name:roc age:18 height:190

类方法 & 对象操作符

类方法 static

  • 静态方法(类方法)不能访问非静态成员
  • 实例方法 即可访问静态成员,亦可访问非静态成员
  • 理解访问原理:
    • 实例未被创建的时候哪来的实力对象,这就是类方法中不能访问实例对象的原因
    • 实例创建的时候类的信息也被加载到内存中,这也是实例能够访问静态成员的原因
    • 究其根本:是dart语言作者对整个访问流程的控制
class StaticClass{
  // 静态属性
  static num count = 0;

  // 静态方法
  static sum1(a,b){
    return a + b;
  }
  // 实例方法 访问静态变量
  num sum2(a,b) =>  a + count + b;
}

// 类方法 和 类属性
  num count = StaticClass.sum1(20,50);
  StaticClass.count = count;
  print(StaticClass.count); // 70
  // 实例方法
  StaticClass st = StaticClass();
  num totalCount = st.sum2(60, 70);
  print(totalCount);       // 200
  • 类中定义的常量用static修饰,否则报错
class Rcperson1 {
  String? name;
  num? age;
  // 类中的常量用static修饰
  static const String str = 'hi';
  void run(){
    print('name:$name age:$age');
  }
}
  • dynamic 类型可以为null,可用‘?’修饰对象,否则对象不存在时会报错,容错处理的一种手段
    • 对于dynamic在访问成员的时候加上‘?’ 如:st2?.sum(60,70);
    • 具体类型在声明时就可加上'?' 如:String? ct4;
      案例1
  var st2;
  st2 = StaticClass();
  num ct1 = st2.sum2(60,70);
  print(ct1);
  st2 = null;
  var ct2 = st2?.sum(60,70);
  print(ct2); // null
  var ct3 = st2.sum(60,70);
  print(ct3); // 报错

案例2

String? ct4;// 有 '?'
  ct4 = 'roc';
  ct4 = null;
  print(ct4); // null
  
  String ct5; // 没 '?'
  ct5 = 'roc';
  ct5 = null;
  print(ct5); // 报错 非可选类型不能赋值为null

对象操作符 as is ..

  • 强制类型转换符 as

    • StaticClass zz = cc as StaticClass

方式一

var cc;
  cc = Object();
  cc = StaticClass(); // 准备调用sum2(),没有发现sum2()
  // 强转 调用
  StaticClass zz = cc as StaticClass;
  num zzNum = zz.sum2(60, 70);
  print(zzNum); // 200
  // 强转之后 cc的类型
  print(zz.runtimeType);// StaticClass

方式二

var cc;
  cc = Object();
  cc = StaticClass(); // 准备调用sum2(),没有发现sum2()
  // 强转 调用
  num ccNum = (cc as StaticClass).sum2(60, 70);
  print(ccNum); // 200
  // 强转之后 cc的类型
  print(cc.runtimeType);// StaticClass
  • 类型判断符 is
// 类型判断(自省)
  bool hasStaticClass = zz is StaticClass;
  print(hasStaticClass); // true
  • 链式编程符 ..

  • 对象使用'..'符号操作访问成员之后会返回对象本身,这就是链式编程产生的原理

// 链式编程符 每次调用返回对象本身
  var customObject = zz..sum2(60, 70)..sum2(80, 90)..sum2(100, 110);
  print(customObject.runtimeType); // StaticClass

继承 extends

  • dart是单继承

  • 子类会继承所有的属性和方法(构造方法除外)

// 继承
class K {
  String? name;
  num? age;
  final _height = 111;
  bool get isFree => _height < 110;
  run(){
    debugPrint('K Running..');
  }
}

class KK extends K{
  @override
  // TODO: implement isFree
  bool get isFree => age! < 18;
  void study(){
    debugPrint('KK 在认真学习..');
  }
}
  • 多态
// 多态
void extendsDemo2(){
  K k = KK();
  k.run();
  if (k is KK) {
    k.name = 'roc';
    k.age = 17;
    k.study();
    k.run();
  }
  bool hasFree = k.isFree;
  debugPrint('是否免费:$hasFree');
  • 重写toString

    • 相当于当前类的描述信息
 @override
  String toString() {
    // TODO: implement toString
    String type = this.runtimeType.toString();
    return '$type Type';
  }

// KK Type
  • 子类会默认继承父类的默认构造方法
    • 父类若定义类自己的构造方法,继承的子类必须重写,否则报错

方式一

class KPerson{
  String? name;
  KPerson.withName(this.name);
  KPerson.init();
  KPerson(this.name);
}

class KStudent extends KPerson{
  String? name;
  // 子类中至少重写一个父类的构造方法
  KStudent(this.name):super(name);
  KStudent.init():super.init();
  KStudent.withName(this.name):super.withName(name);
}

方式二

class KPerson{
  String? name;
  KPerson.init();
  KPerson.withName(this.name);
  KPerson(this.name);
}

class KStudent extends KPerson{
  final String? subName;
  // 子类中至少重写一个父类的构造方法
  KStudent.init():subName = 'roc',super.init();
  KStudent.withName(String? hasName): subName = hasName ,super.withName(hasName);
  KStudent(String? hasName): subName = hasName,super(hasName);
}

提示 初始化列表放在super前面

抽象类 & 接口

抽象类 单继承

  • 抽象类不能被实例化,使用abstract修饰
// 提示 方法最好使用驼峰命名,否则编译器会警告
// 定义一个抽象类
abstract class KAbstractClass{
  // 定义一个抽象方法 类似于ios中的protocol
  num kSum(a,b);
}

class KAbstractSubClass extends KAbstractClass{
  @override
  num kSum(a, b) {
    // TODO: implement kSum
    return a + b;
  }
}

void abstractDemo(){

  // 不需要is判断,可直接使用子类成员
  KAbstractClass as = KAbstractSubClass();
  num count = as.kSum(60, 70);
  debugPrint(count.toString());
}

// 结果130 
  • 注意是 debugPrint 不会报警告一切打印由字符串信息输出,打包时不用去除(推荐使用)

接口 implements 多实现

// 定义三个抽象类
abstract class KAbstractClass1{
  // 定义一个抽象方法 类似于ios中的protocol
  num kSum1(a,b);
}

abstract class KAbstractClass2{
  // 定义一个抽象方法 类似于ios中的protocol
  num kSum2(a,b);
}

abstract class KAbstractClass3{
  // 定义一个抽象方法 类似于ios中的protocol
  num kSum3(a,b);
}
class MAbstractSubClass implements KAbstractClass1,KAbstractClass2,KAbstractClass3{
  @override
  num kSum1(a, b) {
    // TODO: implement kSum1
    return a ~/ b;
  }
  @override
  num kSum2(a, b) {
    // TODO: implement kSum2
    return a * b;
  }
  @override
  num kSum3(a, b) {
    // TODO: implement kSum3
    return a - b;
  }
}

void implementsDemo(){
  MAbstractSubClass hasObject = MAbstractSubClass();
  num c1 = hasObject.kSum1(20000, 1);
  num c2 = hasObject.kSum2(10000, 2);
  num c3 = hasObject.kSum3(30000, 10000);
  debugPrint(c1.toString()); // 20000
  debugPrint(c2.toString()); // 20000
  debugPrint(c3.toString()); // 20000
}

Mixins 混入 多继承

  • 1.有构造方法的类,不能用来混入
  • 2.混入的类不能继承自Object之外的其他类,要保持单纯

方式一

class A {
  message()=> debugPrint('A...');
  send1()=> debugPrint('s1...');
}
class B {
  message()=> debugPrint('B...');
  send2()=> debugPrint('s2...');
}

class D {
  message()=> debugPrint('D...');
  send3()=> debugPrint('s3...');
}

// C继承自A,BD则是混入的类
class C extends A with B,D{
  centerMessage()=> debugPrint('CM...');
}


void MixinClassDemo1(){
  C hasObject = C();
  hasObject.send1();
  hasObject.send2();
  hasObject.send3();
  hasObject.message();
  hasObject.centerMessage();
  }
  // 打印
  s1...
  s2...
  s3...
  D... 重点细节:message 打印的是最后一个混入类D的成员
  CM...

方式二

class A {
  message()=> debugPrint('A...');
  send1()=> debugPrint('s1...');
}
class B {
  message()=> debugPrint('B...');
  send2()=> debugPrint('s2...');
}
class D {
  message()=> debugPrint('D...');
  send3()=> debugPrint('s3...');
}
class F {
  message()=> debugPrint('F...');
}

// 推荐使用
class Fs = A with B,D,F;

void MixinClassDemo2() {
  Fs hasObject = Fs();
  hasObject.send1();
  hasObject.send2();
  hasObject.send3();
  hasObject.message();
}

// 打印
s1...
s2...
s3...
F...
  • 重载操作符 operator
class KOperatorClass{
  num age;
  KOperatorClass(this.age);
  // 重载操作符 > 大于号
  bool operator > (KOperatorClass otherObject) => age > otherObject.age;
}

// 使用
void kOperatorDemo(){
  KOperatorClass k1 = KOperatorClass(36);
  KOperatorClass k2 = KOperatorClass(18);
  bool has = k1 > k2;
  debugPrint(has.toString()); // true
}

你可能感兴趣的:(Dart2 class & object)