typescript封装属性、public、private、protected、constructor、get、set、extends

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// 自执行函数的作用是形成单独模块(块作用域),
// 防止此文件的变量或方法与其他文件的属性或方法冲突
(function () {<!-- -->
    // 可以任意修改类中属性的值
    class ArbitrarilyEdit {<!-- -->
        name: string;
        age: number;

        constructor(name: string, age: number) {<!-- -->
            this.name = name;
            this.age = age;
        }
    }

    let arbitrarilyEdit = new ArbitrarilyEdit('半晨', 24);

    // 在对象中直接设置属性
    // 属性可以任意的被修改
    // 属性可以任意被修改将会导致对象中的数据变得非常不安全
    console.log('before-arbitrarilyEdit:', arbitrarilyEdit);
    // before-arbitrarilyEdit: ArbitrarilyEdit {name: "半晨", age: 24}
    arbitrarilyEdit.name = '舒冬';
    arbitrarilyEdit.age = -33;
    console.log('after-arbitrarilyEdit:', arbitrarilyEdit);
    // arbitrarilyEdit: ArbitrarilyEdit {name: "舒冬", age: -33}

    // 定义一个不可以任意修改类中值的类
    class Person {<!-- -->
        // typescript可以在属性前添加属性的修饰符
        // public 修饰的属性可以在任意位置访问(修改) 默认值
        // private 私有属性,私有属性只能在类内部进行访问(修改)
        // 通过在类中添加方法使得私有属性可以被外部访问
        // protected 受包含的属性,只能在当前类和当前类的子类中访问(修改)
        private _name: string;
        private _age: number;

        constructor(name: string, age: number) {<!-- -->
            this._name = name;
            this._age = age;
        }

        // getter方法用来读取属性
        // setter方法用来设置属性
        // 它们被称为属性的存取器

        // 定义方法,用来获取name属性
        getName() {<!-- -->
            return this._name;
        }

        // 定义方法,用来设置name属性
        setName(value: string) {<!-- -->
            this._name = value;
        }

        getAge() {<!-- -->
            return this._age;
        }

        setAge(value: number) {<!-- -->
            // 判断年龄是否合法
            if (value >= 0) {<!-- -->
                this._age = value;
            }
        }

        get name() {<!-- -->
            return this._name;
        }

        set name(value) {<!-- -->
            this._name = value;
        }

        get age() {<!-- -->
            return this._age;
        }

        set age(value) {<!-- -->
            if (value >= 0) {<!-- -->
                this._age = value
            }
        }
    }

    const per = new Person('半晨', 18);

    console.log('before-per:', per);
    // before-per: Person {_name: "半晨", _age: 18}
    per._name = '舒冬';
    per._age = -36;
    console.log('after-per:', per);
    // after-per: Person {_name: "舒冬", _age: -36}
    // 此时是可以编译通过
    // 但是_name和_age会出现下波浪线提示错误

    // 定义方法,获取name属性
    console.log('getName:', per.getName());
    // getName: 舒冬
    // 定义方法,设置name属性
    per.setName('苏檀');
    console.log('setName:', per.getName());
    // setName: 苏檀

    // 定义方法,获取age属性
    console.log('getAge:', per.getAge());
    // getAge: -36
    // 定义方法,设置age属性
    // 此处无法修改原先赋值为 -36 的值
    per.setAge(-16);
    console.log('setAge:', per.getAge());
    // setAge: -36

    // 使用自带的get和set方法
    console.log('before-getName:', per.name);
    // before-getName: 苏檀
    console.log('before-age:', per.age);
    // before-age: -36
    per.name = '宁毅';
    per.age = 36;
    console.log('after-getName:', per.name);
    // after-getName: 宁毅
    console.log('after-age:', per.age);
    // after-age: 36

    // ----------------------------------------------------------
    class A {<!-- -->
        // protected 受包含的属性,只能在当前类和当前类的子类中访问(修改)
        protected num: number;

        constructor(num: number) {<!-- -->
            this.num = num;
        }
    }

    class B extends A {<!-- -->
        test() {<!-- -->
            console.log(this.num);
            // 33
        }
    }

    const b = new B(3436);
    console.log('before-b:', b);
    // before-b: B {num: 3436}
    b.num = 33;
    // 属性“num”受保护,只能在类“A”及其子类中访问。
    console.log('after-b:', b);
    // after-b: B {num: 33}
    // 本来是不应该修改的,
    // 但是编译时没有限制报错不能生成文件导致结果是可以修改
    b.test();

    // ----------------------------------------------------------
    // 方式一和方式二是一样的效果
    // class C {<!-- -->
    //     name: string;
    //     age: number

    //     // 可以直接将属性定义在构造函数中
    //     constructor(name: string, age: number) {<!-- -->
    //         this.name = name;
    //         this.age = age;
    //     }
    // }

    // 方式二和方式一是一样的效果
    class C {<!-- -->
        // 可以直接将属性定义在构造函数中
        constructor(public name: string, public age: number) {<!-- -->
            console.log(name, age);
            // xxx 111
        }
    }

    const c = new C('xxx', 111);
    console.log('c:', c);
    // c: C {name: "xxx", age: 111}
})();