# Dart 类 Class 继承多态(一)

# 一:类的声明与使用

# 1,声明一个 Person 类

lib/Person.dart 声明一个 Person class:

class Person{
    String name;
    int age;
    int sex;
    // 普通构造函数
    Person(String name, int age, [int sex=1]){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    // 方法声明
    void getInfo(){
        print('My name is ${name}, my age is ${age}, and I am a ${sex===1?'man':'woman'}');
    }
    void changeName(String name){
        if(name !== null){
            this.name = name;
        }
    }
}

# 2,类的引入

在 dart 文件中引入 Person 类:

import 'lib/Person.dart';

# 3,实例化 Person 类

Person p = new Person('asdfs', 123, 1);
p.getInfo();
p.changeName('123123asdas');
p.getInfo();
<!-- 输出结果 -->
flutter: ------------
flutter: My name is asdfs, my age is 123, and I am a man
flutter: ------------
flutter: My name is 123123asdas, my age is 123, and I am a man

# 4,私有属性以及私有方法

class Person {
    // ...
    String _secret; // 私有属性,只在本class有效
    // ...
    // 私有方法
    void _run(){
        print('private function _run');
    }
    // 对外暴露私有方法
    void executeRun(){
        this._run();
    }
}

访问私有属性和方法

Person p4 = new Person.secret('_secret message');
print(p4.getSecret());
p4.setSecret('new _secret message');
print(p4.getSecret());

# 5,命名构造函数

命名构造函数容许多个不同名称构造函数的存在,调用不同名称的构造函数,可以实例化出不同的实例。

Person.now(){
    print(new DateTime.now());
}
Person.setInfo(this.name,this.age,[this.sex])
Person.secret(this._secret);

使用命名构造函数:

Person p2 = new Person.now();
print(p2); // Instance of 'Person'
p2.getInfo();
p2.changeName('postburd');
p2.getInfo();



Person p3 = new Person.setInfo();
p3.getInfo();
p3.changeName('sfasdf');
p3.getInfo();

# 6,getter 和 setter

getter 和 setter 可以最大程度简化值的获取或者格式化以及设置

String get school=>_school;
// stu1.school = '987';
get info{
    return 'My name is ${name}, my age is ${age}, and i am a ${sex == 1?'man':'woman'}';
}
set newName(String name){
    if(name != null){
        this.name = name;
    }
}

使用

Person p5 = new Person('postbid', 20);
print(p5.info);
p5.newName = 'sadfsdaf';
print(p5.info);

# 7,初始化构造列表

初始化构造函数可以默认初始化一个值,不过单个 class 上没有实际意义
在子类上初始化列表

String defaultCountry;
Person(String name, int age, [int sex = 1]):defaultCountry = 'CN'{
    this.name = name;
    this.age = age;
    this.sex = sex;
}

class Children extends Person{
    String _family;
    int country;
    String name;
    // 在子类构造器方法体之前,可以初始化实例变量
    Person(this._family, String name, int age, {this.country = 'China'})
    :
    name = '$_family.$country',
    // 如果父类没有默认(无参)的构造方法,则需要在初始化列表中调用父类的构造方法进行初始化
    super(name,age){
        // 类的方法体(不是必须的)
        print(name,age);
    };
}




Person p6 = new Person('postbird', 20);
print(p6.defaultCountry);

# 简写构造函数

如果构造函数没有特殊逻辑处理,可以使用简写的构造函数

Person(this.name, this.age, [this.sex]);

# 静态成员

静态方法只能访问静态属性,不能访问非静态属性。
非静态方法可以正常访问静态属性。

class Person {
    static String name;
    int age;

    static void setName(String name){
        Person.name = name;
        // this.age = 20; // err,静态方法只能访问静态属性
    }
    void printName(){
        print('name is ${Person.name}');
    }
}

# isas..操作符

如果实例存在则调用,否则不调用
is 判断是否归属于某个类或者子类
as 声明某个实例当做某个类使用,比如子类as父类
.. 级联操作符,用于串联操作
代码示例:

import 'demo6.dart';
class Person {
    String name;
    int age;
    Person(this.name,this.age);
    void printInfo(){
        print('name is $name, age is $age');
    }
}
void main(){
    print('--------?条件运算符--------');
    Person p1;
    p1?.printInfo();
    Person p2 = new Person('postbird', 20);
    p2?.printInfo();
    print('--------is--------');
    if(p2 is Person){
        p2.name = 'newPers';
    }
    p2.printInfo();
    print('-------as--------');
    var p3 = p2;
    (p3 as Person).name='newOtss';
    p3.printInfo();
    (p3 as Person).printInfo();

    print('-------..级联操作符--------');
    Person p4 = new Person('XImo', 20);
    p4..name = 'new Name'
        ..age = 22
        ..printInfo();
}

# extends 继承

子类继承父类使用extends关键字,
重写方法要加@override注释,便于协作
子类构造方法中,如果要初始化父类构造方法,使用super关键字,比如 Dog(String name,int age,[String nickName]): super(name, age),子类中调用父类的方法使用super.fun();

class Animal {
    String name;
    int age;
    // 标准构造方法
    Animal(this.name,this.age);
    void speak(){}
    void printInfo(){
        print('name is $name');
    }
    void parentPrint(){
        print('i am parent');
    }
}
class Dog extends Animal {
    String nickName;
    Dog(String name, int age, [String nickName]): super(name, age); // 完成父类初始化,才能开始子类的初始化

    
    void speak(){
        this.parentPrint();
        super.parentPrint();
        print('wang wang!!');
    }
    void setNickName(String name){
        if(name!=null){
            this.nickName = name;
        }
    }
    get fullInfo{
        return {
            'name': this.name,
            'age': this.age,
            'nickName': this.nickName
        };
    }
}
void main(){
    print('-----继承-----');
    Dog d = new Dog('qiu', 3, 'kitty');
    d.printInfo();
    d.speak();
    d.setNickName('Nicjsdsa');
    print(d.fullInfo);
}

# 类的多态

通俗讲,父类可以调用子类同名的方法,输出结果和子类相同,但不能调用父类没有子类中有的方法,也就是子类的方法覆盖了父类的方法 比如:Animal d1=new Dog(),因为 d1 类型是 Animal,因此d1.speak()=>实际上调用 d1 子类方法差不多,但 Animal 没有run,所以不能调用d1.run()

class Animal {
    speak(){}
}
class Dog extends Animal {
    
    speak(){
        print('wang wang!!');
    }
    run(){
        print('bey bey!!');
    }
}
void main(){
    Animal d1 = new Dog();
    Dog d2 = new Dog();
    d1.run(); // err
    d1.speak();
    d2.run();
}