Day 11 - Class 类与面向对象

Day 11 - Class 类与面向对象 Day 11 - Class 类与面向对象今天学完你能做什么用class关键字创建自己的类型理解constructor、extends、super、static用getter/setter做属性保护写出面向对象的代码结构一、为什么需要 Class——用汽车工厂来理解1.1 没有 Class 之前——手动造车// 造三辆车每辆都要手动写一遍属性constcar1{brand:宝马,speed:0,accelerate(){this.speed10;},brake(){this.speed-5;}};constcar2{brand:奔驰,speed:0,accelerate(){this.speed10;},brake(){this.speed-5;}};// 每造一辆车都要重复写 accelerate 和 brake疯了1.2 Class 就是汽车模具// 一个模具批量生产classCar{brand:string;speed:number0;constructor(brand:string){this.brandbrand;// this 指向当前这辆车}accelerate(){this.speed10;console.log(${this.brand}加速当前速度${this.speed});}brake(){this.speedMath.max(0,this.speed-5);console.log(${this.brand}刹车当前速度${this.speed});}}// 用模具造车——new 一下就行constbmwnewCar(宝马);constbenznewCar(奔驰);bmw.accelerate();// 宝马 加速当前速度 10bmw.accelerate();// 宝马 加速当前速度 20benz.accelerate();// 奔驰 加速当前速度 10// 两辆车各自独立类比Class 汽车模具图纸new 用模具造一辆真实的车this 当前这辆车自己。二、Class 的四大构件2.1 constructor —— “出厂设置”classStudent{name:string;age:number;school:string;constructor(name:string,age:number){this.namename;this.ageage;this.school第一中学;// 固定默认值console.log(${name}入学了);}}consts1newStudent(小明,12);// 小明 入学了consts2newStudent(小红,13);// 小红 入学了constructor是创建对象时自动调用的函数。就像买车时填的登记表——你填什么品牌、颜色工厂就给你造什么样的车。2.2 属性——“车有什么”classPhone{brand:string;// 普通属性price:number;readonlyimei:string;// 只读属性——出厂后不能改privatebatteryLevel100;// 私有属性——外部无法访问constructor(brand:string,price:number,imei:string){this.brandbrand;this.priceprice;this.imeiimei;}useBattery(){this.batteryLevel-10;}}constphonenewPhone(华为,5999,IMEI123456);// phone.imei xxx; // ❌ readonly 不能改// phone.batteryLevel; // ❌ private 不能访问phone.useBattery();// ✅ 通过方法间接操作2.3 方法——“车能做什么”classCalculator{privateresult0;add(n:number):this{// 返回 this 可以链式调用this.resultn;returnthis;}sub(n:number):this{this.result-n;returnthis;}getResult():number{returnthis.result;}}constcalcnewCalculator();calc.add(10).sub(3).add(5);// 链式调用10 - 3 5console.log(calc.getResult());// 122.4 getter / setter —— 给属性加门禁classTemperature{private_celsius0;// getter读取时自动调用getcelsius():number{returnthis._celsius;}// setter赋值时自动调用setcelsius(value:number){if(value-273.15){thrownewError(温度不能低于绝对零度);}this._celsiusvalue;}// 计算属性getfahrenheit():number{returnthis._celsius*9/532;}}consttempnewTemperature();temp.celsius25;// 触发 setter —— 验证通过console.log(temp.celsius);// 25 —— 触发 getterconsole.log(temp.fahrenheit);// 77 —— 计算属性看起来像属性实际是方法// temp.celsius -300; // ❌ 触发 setter 验证——报错三、继承 —— 儿子继承父亲的家产3.1 extends —— “我继承你的一切”// 父类通用动物classAnimal{name:string;constructor(name:string){this.namename;}move(){console.log(${this.name}在移动);}}// 子类狗继承自动物classDogextendsAnimal{breed:string;constructor(name:string,breed:string){super(name);// 必须调用父类的 constructorthis.breedbreed;}bark(){console.log(${this.name}(${this.breed}) 汪汪叫);}// 重写父类方法move(){console.log(${this.name}摇着尾巴跑);}}constdognewDog(旺财,金毛);dog.move();// 旺财 摇着尾巴跑 —— 重写后的版本dog.bark();// 旺财 (金毛) 汪汪叫 —— 自己的方法类比儿子继承父亲的房子、车子属性和方法但儿子也可以有自己的新东西新方法或者改装父亲的东西重写 move。3.2 super —— 调用父类classBirdextendsAnimal{constructor(name:string){super(name);// 调用父类 constructor}move(){super.move();// 先执行父类的 moveconsole.log(然后飞起来了);// 再加自己的逻辑}}constbirdnewBird(小鹦鹉);bird.move();// 小鹦鹉 在移动 ← 父类的// 然后飞起来了 ← 自己的四、static —— 属于工厂的不属于某辆车classMathUtils{staticPI3.14159;// 静态属性——属于类本身staticadd(a:number,b:number):number{// 静态方法returnab;}staticrandom(min:number,max:number):number{returnMath.floor(Math.random()*(max-min1))min;}}// 静态属性和方法不需要 new直接用类名调用console.log(MathUtils.PI);// 3.14159console.log(MathUtils.add(1,2));// 3console.log(MathUtils.random(1,100));// 随机数// 不能通过实例访问constmunewMathUtils();// mu.add(1, 2); // ❌ 报错类比static是贴在工厂墙上的规章制度不属于任何一辆车。所有车都遵守但你不能说这辆车的规章制度。五、public / private / protectedclassBankAccount{publicaccountNumber:string;// 公开——谁都能看privatebalance:number;// 私有——只有自己能看protectedownerName:string;// 受保护——自己和子类能看constructor(accountNumber:string,ownerName:string,balance:number){this.accountNumberaccountNumber;this.ownerNameownerName;this.balancebalance;}getBalance():number{returnthis.balance;}}classSavingsAccountextendsBankAccount{showOwner(){console.log(this.ownerName);// ✅ protected 子类可以访问// console.log(this.balance); // ❌ private 子类也不能访问}}constaccountnewBankAccount(6222-1234,张三,10000);console.log(account.accountNumber);// ✅ public// console.log(account.balance); // ❌ private// console.log(account.ownerName); // ❌ protectedconsole.log(account.getBalance());// ✅ 通过公开方法访问修饰符类内部子类外部public✅✅✅protected✅✅❌private✅❌❌六、abstract —— “你必须自己实现”// 抽象类不能直接 new只能被继承abstractclassShape{abstractgetArea():number;// 抽象方法——子类必须实现describe():string{// 普通方法——子类直接继承return面积是${this.getArea()};}}classCircleextendsShape{constructor(privateradius:number){super();}getArea():number{returnMath.PI*this.radius**2;}}classRectangleextendsShape{constructor(privatewidth:number,privateheight:number){super();}getArea():number{returnthis.width*this.height;}}constcirclenewCircle(5);console.log(circle.describe());// 面积是 78.539...constrectnewRectangle(4,6);console.log(rect.describe());// 面积是 24类比abstract像一份合同模板——关键条款abstract 方法留白签合同的子类自己填。七、Class 实战一个完整的用户管理系统abstractclassBaseModel{constructor(publicid:number,publiccreatedAt:DatenewDate()){}abstracttoJSON():Recordstring,any;}classUserextendsBaseModel{constructor(id:number,publicname:string,publicemail:string,private_password:string,publicrole:admin|useruser){super(id);}getisAdmin():boolean{returnthis.roleadmin;}changePassword(oldPwd:string,newPwd:string):boolean{if(oldPwd!this._password)returnfalse;this._passwordnewPwd;returntrue;}toJSON(){return{id:this.id,name:this.name,email:this.email,role:this.role,isAdmin:this.isAdmin,createdAt:this.createdAt// _password 不暴露};}}constusernewUser(1,张三,zstest.com,123456,admin);console.log(user.toJSON());console.log(修改密码:,user.changePassword(123456,newpass));// trueconsole.log(错误密码:,user.changePassword(wrong,newpass));// false今日小结┌──────────────────────────────────────────┐ │ │ │ Class 对象模具new 一下批量生产 │ │ constructor 出厂设置new 时自动执行 │ │ this 当前这个实例自己 │ │ │ │ extends 继承父类的属性和方法 │ │ super 调用父类的 constructor/方法 │ │ static 属于类本身不用 new │ │ │ │ getter/setter 给属性加验证和计算 │ │ public/private/protected 访问控制 │ │ abstract 强制子类实现 │ │ │ │ 口诀class 做模具new 出实例 │ │ extends 继承static 共享 │ │ │ └──────────────────────────────────────────┘