Dart 学习笔记 面向对象(二)

270 阅读6分钟

笔记来源:

笔记意在快速入门,主要记录一些与Java不同的语法用法

基本特性

  • class声明一个类
  • 使用new 来创建一个对象
  • 所有对象都继承object
  • Dart中的可见性以library(库)为单位
  • 默认情况下,每一个Dart文件就是一个库

关键符 _ 前缀表示私有性

  //带下划线 表示私有类
  class _Person{
  	String _name;//私有 成员变量
  	int age;
  	
  	void _print(){// 私有方法
  		print("haha");
  	}
  }

计算属性(关键字 get、set,意义如例子显示,面积更像是Rect的固有属性)

class Rect{
  num width,height;
  //get 计算属性  可以由已有的成员变量通过计算获得所需值
  num get area => width * height;
      //set 赋值
      set area(value){
        width = value;
      }
}

构造方法

  • 没有定义时有默认的构造方法(clazz(){}

  • 预设参 构造方法

    class Person {
    	String name;
    	int age;
        final String sex;
        //预设参 可以对final修饰的变量赋值
    	Person(this.name,this.age,this.sex);
    	//等同于
        //但不能对final修饰的变量赋值
    	Person(String name,int age){
    		this.name = name;
    		this.age= age;
    	}
    }
    
  • 构造方法不能重载,如果需要多个构造方法,使用命名构造方法

    var person = Person.withName("zhangsan");
    
    //命名构造方法
    Person.withName(String name){
    	this.name = name;
    }
    
  • 常量构造方法

    • 如果类是不可变状态,可以把对象定义为编译时常量
    • 使用const 声明构造方法,并且所有变量都为final
    • 使用const声明对象,可以省略
    • 更快
    void main(){
    	//person 和 p2 都不课再重新赋值了
    	const person = const Person("lisi",24);//第二个const可省略
    	const p2 = Person("wanwu",25);
    }
    
    class Person(){
    	//成员变量 使用final修饰
    	final String name;
    	final int age;
        //const 声明构造方法
    	const Person(this.name,this.age);
    	void work(){
    		print("...")
    	}
    }
    
  • 工厂构造方法

    • 工厂构造方法类似与设计模式中的工厂模式
    • 在构造方法前添加 关键字 factory 实现一个工厂构造方法
    • 工厂构造方法中可返回对象
    //示例功能基本与工厂模式相同
    class Logger {
      final String name;
      //缓存Map
      static final Map<String,Logger> _cache = new Map<String,Logger>();
      //使用关键字factory 工厂构造方法 有返回值 返回当前类
      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){
        print(msg);
      }
    }
    

初始化列表

class Person {
	String name;
	int age;
    final String sex;
    //预设参 可以对final修饰的变量赋值
	Person(this.name,this.age,this.sex);
	//冒号后面添加表达式
    //多个表达式用逗号分开
    //冒号后面的初始化列表 在构造函数执行前执行,可以对final修饰的对象进行赋值
	Person.withMap(Map map):name = map["name"],gender = map["gender"]{
		this.age = age;
	}
}

静态成员(使用与java一样)

  • 使用static 关键字 声明
  • 静态成员不能访问非静态成员,非静态成员可以访问静态成员
  • 类中的常量需要使用static const声明

对象操作符

  • 条件成员访问:(和kotlin类似使用)

  • 类型转换: as

  • 是否指定类型 : is、is!

  • 级联操作..

    //级联操作这样玩的
    new Person()..name = "zhangsan"
    			..age = 23
    			..work();
    
    class Person(){
    	//成员变量 使用final修饰
    	final String name;
    	final int age;
        //const 声明构造方法
    	const Person(this.name,this.age);
    	void work(){
    		print("...")
    	}
    }
    

    对象call方法

    • call() 方法是一种特殊的类的方法,将对象作为方法来调用就是直接调用对象中的call方法

      class Person(){
      	
      	String call(String name){
      		return "call me $name";
      	}
      }
      //新建对象
      var person = new Person();
      //直接调用对象
      print(person("zhangsan"));
      //输出  call me zhangsan
      

高级特性

继承

  • 关键字 extends 继承一个类
  • 子类会继承父类的可见属性和方法,不会继承构造方法
  • 子类能够复写父类的方法 setting getting
  • 单继承 多态

继承中的构造方法

  • 子类的构造方法默认回调用父类的无名无参的构造方法

  • 如果父类没有无名无参构造方法,则需要显性的去调用父类的构造方法

  • 在构造方法后使用 : 父类的构造方法

    class Stu extends Person{
      int age;
      Stu.withName(String name) : super.withName(name);
    }
    
    class Person{
      String name;
      Person(this.name);
      Person.withName(this.name);
    }
    
  • 构造方法的执行顺序

    • 父类的构造方法会在子类的构造方法之前执行
    • 初始化列表 会在 所有的构造方法之前执行

抽象类

  • 抽象类使用 abstract 修饰,不能直接实例化
  • 抽象方法不用 abstract 修饰 无实现
  • 抽象类可以没有抽象方法
  • 有抽象方法的类一定得声明为抽象类

接口

  • 类和接口是统一的 类就是接口
  • 使用 implements 来实现 类,会被要求重写类中所有的 变量 和方法(所以这种接口有什么用?

Mixins

  • Mixins 类似于多继承,是在多类继承中重用一个类代码的方式
  • 作为Mixin的类不能有手动显示声明构造方法
  • 作为Mixin的类只能继承字Object,也就是说不能再手动继承其它类
  • 使用关键字 with 连接一个或多个 mixin
void main(){
  var d = new D();
  //如果继承的类A 和Mixin类B、C都有调用方法 a() 则会调用排在最后的 C 的方法a()
  d.a();
}
//with 后面的 B、C 就是Mixin 类
//不能有显性构造方法
//不能继承其他类
class D extends A with B,C{
}
class A {
  void a(){
    print("A.a......");
  }
  void b(){
    print("A.b.....");
  }
}
class B{
  void a(){
    print("B.a......");
  }
  void b(){
    print("B.b.....");
  }
}
class C{
  void a(){
    print("C.a......");
  }
  void b(){
    print("C.b.....");
  }
}
  • 使用Mixin的组装功能
/**
* 任务:需要做一台只有一种算法的计算器
**/
//首先必须项 计算器 必须有 数字
class Number {
  int num;
}
//可选项 加法芯片
class Add {
  void work() {
    print("加法运算中...");
  }
}
//可选项 减法芯片
class Minus  {
  void work() {
    print("减法运算中...");
  }
}
//还可以有 乘、除...
//先组装一台有加法的计算器
class Calculator1 = Number with Add;
//再组装一台有减法的计算器
class Calculator2 = Number with Minus;
//Over 可以直接使用了

操作符覆写

  • 覆写操作符需要再类中定义 格式如下

    返回类型  operator 操作符(参数1,参数2,..){
    	实现体
    	return 返回值;
    }
    
  • 如果覆写==,还需要覆写对象中的hashCode getting 方法

  • 可覆写的一些操作符有:<、+、—、|、[]、>、[]=、>>、==、~/ 等

    class Person{
    	int age;
    	Person(this.age);
    	//覆写 > 使用年龄 来判断 Person 的大小
    	bool operator >(Person person){
    		return this.age > person.age;
    	}
        //覆写 []
    	int operate [](String str){
    		if("age" == str){
    		 	return age;
    		}
    		return 0;
    	}
    }