Dart 类

56 阅读2分钟

Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类,一个类通常由属性和方法组成

class Person {
    String name = "zhangsan"
    int age = 23
    //构造函数
    Person(){
        print("这是构造函数的内容这个方法在实例化的时候触发")
    }
    void getInfo(){
        //print("$name----$age")
        print("${this.name}-----${this.age}")
    }
}
class Person {
    String name
    int age
    //默认构造函数(只能写一个,有了自己的构造函数就会覆盖默认的构造函数Person())
    Person(String name,int age){
        this.name = name
        this.age = age
        print("这是构造函数的内容这个方法在实例化的时候触发")
    }
    /*
       默认构造函数的简写
      Person(this.name,this.age)
    */
    // 命名构造函数可以写多个
    Person.now(){
        print("我是命名构造函数")
    }
    Person.setInfo(String name,int age){
        this.name = name
        this.age = age
    }
    //命名工厂构造方法:factory 【类名 + 方法名】
    //它可以有返回值,而且不需要将类的final变量作为参数,是提供一种灵活获取类的对象模式
    factory Person.per(Person per){
        return Person(stu.name, stu.age)
    }
    void getInfo(){
        //print("$name----$age")
        print("${this.name}-----${this.age}")
    }
}

Dart中我们那也可以在构造函数体运行之前初始化实例变量

class Rect {
    num height
    num width
    // height = 2,width = 10 在类初始化的时候设置默认值
    Rect(this.height,this.width):height = 2,width = 10{
    
    }
    set areaHeight(value) {
        this.height = value
    }
}

Rect r = new Rect(10,4)
r.areaHeight = 6
print("面积:${r.area}") // 注意调用直接通过访问属性的方式访问area

构造函数的重定向

在一个构造函数中,去调用另外一个构造函数(注意:是在冒号后使用this调用)

class Person {
    String name;
    int age;
    
    Person(String name):this._internal(name,0);
    Person._internal(this.name,this.age)
}

常量构造方法

在某些情况下,传入相同的值,我们希望返回同一个对象,这个时候,可以使用常量构造方法。

默认情况下,创建对象是,即使传入相同的参数,创建出来的也不是同一个对象,看下面代码。

这里我们使用identical(对象1,对象2)函数来判断两个对象是否是同一个对象。

main(List<String> args){
    var p1 = Person('why')
    var p2 = Person('why')
    print(identical(p1,p2))//false
}

class Person {
    String name;
    Person(String name);
}

常量构造函数的写法,常量构造函数只会存在一个。

main(List<String> args){
    const p1 = Person('why')
    const p2 = Person('why')
    print(identical(p1,p2))//true
}


class Person {
    final String name;
    const Person(String name);
}

常量构造方法有一些注意点

  • 注意一:拥有常量构造方法的类中,所有的成员变量必须是final修饰的。
  • 注意二:为了可以通过常量构造方法,创建出相同的对象,不再使用new关键字,而是使用const关键字。
    • 如果是将结果赋值给const修饰的标识符时,const可以省略。

工厂构造方法

工厂构造函数最大的特点:可以手动返回一个对象。普通的构造函数:会自动返回创建的对象,不能手动的返回。

main(List<String> args){
    final p1 = Person.withName('why')
    final p2 = Person.withName('why')
    print(identical(p1,p2))//true
}

class Person {
    String name;
    String color;
    
    static final Map<String,Person> _nameCache = {}
    static final Map<String,Person> _colorCache = {}
    
    factory Person.withName(String name){
        if (_nameCache.containsKey(name)){
            return _nameCache[name]
        }else {
            final p = Person(name,'default')
            _nameCache[name] = p
        }
    }
    factory Person.withColor(String color){
        if (_colorCache.containsKey(color)){
            return _colorCache[color]
        }else {
            final p = Person('default',color)
            _colorCache[color] = p
        }
    }
    Person(this.name,this.color)
}
//不仅仅是构造方法,更是一种模式
//有时候为了返回一个之前已经创建的缓存对象,原始的构造方法已经不能满足要求,那么可以使用工厂模式来定义构造方法
class Logger {
    static Logger _cache;
    factory Logger(){
        if (_ cache == null){
            _cache = Logger._internal();
        }
        return _cache
    }
    Logger._internal();
    void log(String msg){
        print(msg);
    }
}
Logger log1 = Logger()
Logger log2 = Logger()
print(log1 == log2) // true

get 计算属性

class Rect {
    num height
    num width
    Rect(this.height,this.width)
    get area {
        return this.height * this.width
    }
}

Rect r = new Rect(10,4)
print("面积:${r.area}") // 注意调用直接通过访问属性的方式访问area

set

class Rect {
    num height
    num width
    Rect(this.height,this.width)
    set areaHeight(value) {
        this.height = value
    }
}

Rect r = new Rect(10,4)
r.areaHeight = 6
print("面积:${r.area}") // 注意调用直接通过访问属性的方式访问area

继承

  1. 子类使用extends关键字来继承父类
  2. 子类会继承父类里面可见的属性和方法,但是不会继承构造函数
  3. 子类能重写父类的方法 getter 和 setter
class Person {
    String name
    int age
    //构造函数
    Person(this.name,this.age){
        print("这是构造函数的内容这个方法在实例化的时候触发")
    }
    Person.xxx(this.name,this,age)
    void printInfo(){
        print("${this.name}-----${this.age}")
    }
}
class Web extends Person {
    String sex
    Web(String name,num age,String sex):super(name,age){
        this.sex = sex
    }
    // 给命名构造函数传参
    Web(String name,num age,String sex):super.xxx(name,age){
        this.sex = sex
    }
    run(){
        print("${this.name}---${this.age}---${this.sex}")
    }
    @override printInfo(){
        print("${this.name}-----${this.age}---${this.sex}")
    }
}

Web w = new Web("zhangsan",12,'男')
w.printInfo()
w.run()
print(w.name)

访问修饰符

Dart和其他面向对象语言不一样,Dart中没有public private protected这些访问修饰符。但是我们可以使用“_”把一个属性或者方法定义成私有

静态成员

  1. 使用static关键字来实现类级别的变量和函数
  2. 静态方法不能访问非静态成员,非静态方法可以访问静态成员和方法
class Person {
    static String name = "张三"
    int age = 20
    static void show(){
        print(name)
    }
    void printInfo(){
        //非静态方法可以访问静态成员以及非静态成员
        print(name) // 访问静态属性
        print(this.age) // 访问非静态属性
        
        show() // 调用静态方法
    }
    static void printUserInfo(){//静态方法
        print(name) // 静态属性
        show()//调用静态方法
        // print(this.age) 静态方法没法访问非静态的属性和非静态方法
    }
}
print(Person.name) 
Person.show()

Dart中的对象操作符

? 条件运算符 as 类型转换 is 类型判断 ..级联操作(连缀)

Person p = new Person("张三",20)
p?.printInfo()
Person p = new Person("张三",20)
if (p is Person){
    p.name = "李四"
}
p.printInfo()
print(p is Object)
var p1 = ""
p1 = new Person("张三",20)
(p1 as Person).printInfo()
Person p1 = new Person("张三",20)
p1.name = '张三222'
p1.age = 40
p1.printInfo()

//可以写成..
p1..name = '李四'
  ..age = 30
  ..printInfo()