TypeScript-面向对象

1、要想面向对象,操作对象,首先便要拥有对象;

2、要创建对象,必须要先定义类,所谓的类可以理解为对象的模型;

3、程序中可以根据类创建指定类型的对象;

举例来说:

  • 操作浏览器要使用window对象
  • 操作网页要使用document对象
  • 操作控制台要使用console对象

一、定义类

class 类名 {

    属性名: 类型 =;
    
    方法名(){
        ....
    }

}

示例:

    class Person{
    //定义实例属性,需要通过对象实例访问:
	/*
	const per = new Person();  
	per.name;
	*/
        name: string = "张三";
        
    //使用static开头的属性是静态属性(类属性),可以直接通过类访问
    /*
    Person.age;
    */
        static age: number = 18;
    
    
    //使用readonly开头的属性表示一个只读的属性无法修改
    readonly color:string = "blue"
   	//顺序不可颠倒
    readonly static address:string = "shanxi"
    
     sayHello(){
       console.log('hello');
        }
    }

const p = new Person();

p.name;

Person.age

p.sayHello();

二、构造函数

可以使用constructor定义一个构造器方法;

例如:

class Dog {
	name:string;
    age:number;
    constructor(name: string, age: number) {
    //this表示当前实例
    //可以通过this向新建的对象中添加属性
        this.name = name;
        this.age = age;
    }
    bark(){
    //在方法中可以通过this来表示当前调用方法的对象
		consloe.log(this.name)
	}
}
const dog = new Dog('小黑',2)
const dog2 = new Dog('小白',3)
dog.bark()

三、继承

继承时面向对象中的又一个特性

通过继承可以将其他类中的属性和方法引入到当前类中

示例:

class Animal {
    name:string;
    age: number;
    constructor(name:string,age:number){
        this.name = name;
        this.age = age;
    }
    sayHello(){
        console.log('叫声');
    }
}
/*
Dog extends Animal
 - 此时,Animal被称为父类,Dog被称为子类
 - 使用继承后,子类将会拥有父类所有的方法和属性
 - 通过继承可以将多个类共有的代码写在一个父类中
 - 如果希望在子类中添加父类中没有的属性或方法,直接加即可
 - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法,这种形式,我们称之为重写
*/
class Dog extends Animal{
	run(){
		console.log('汪汪')
	}
}
class Cat extends Animal{
	sayHello(){
        console.log('喵喵');
    }
}
const dog = new Dog('旺财',2)
const cat = new Cat('招财',3)
console.log(dog);
console.log(cat);

通过继承可以在不修改类的情况下完成对类的扩展

四、重写

发生继承时,如果子类中的方法会替换掉父类中的同名方法,这就称为方法的重写

示例:

class Animal {
    name:string;
    age: number;
    constructor(name:string,age:number){
        this.name = name;
        this.age = age;
    }
    sayHello(){
        console.log('叫声');
    }
}

class Cat extends Animal{
	sayHello(){
        console.log('喵喵');
    }
}

五、super

在子类中可以使用super 来完成对父类的引用

 class Animal {
        name: string
        constructor(name:string){
            this.name = name
        }
        sayHello(){
            console.log('123');
            
        }
    }
    class Dog extends Animal {
        sayHello(){
            //super表示当前类的父类
            super.sayHello();
        }
    }
    const dog = new Dog('wangcai')
    dog.sayHello() //123

子类继承父类时,必须调用父类的构造方法(如果子类中也定义了构造方法)!

例如:

 class Animal {
        name: string
        constructor(name:string){
            this.name = name
        }
        sayHello(){
            console.log('123');     
        }
    }
    
    class Dog extends Animal {
        age:number;

        constructor(name:string,age:number){
            super(name); //调用父类的构造函数
            this.age = age
        }

        sayHello(){
            //super表示当前类的父类
            super.sayHello();
        }
    }
    const dog = new Dog('wangcai',4)
    dog.sayHello() //123

如果在子类中不调用super将会报错!

六、抽象类(abstract class)

  • 以abstract开头的类是抽象类

  • 抽象类和其他类区别不大,但不能用来创建对象

  • 抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例

  • 使用abstract开头的方法叫做抽象方法,抽象方法没有方法体,只能定义在抽象类中,子类必须对抽象方法进行重写

abstract class Animal {
        name: string
        constructor(name:string){
            this.name = name
        }
        //抽象方法
        abstract sayHello():void
    }
    
    class Dog extends Animal {
        sayHello(){
            console.log('汪汪');
            
        }
    }
    const dog = new Dog('wangcai')
    dog.sayHello() //汪汪

七、接口(Interface)

  • 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法,同时也可以当成类型声明去使用
interface myInterface {
        name:string,
        age:number
    }
interface myInterface {
        gender:string,
    }
const obj:myInterface = {
        name:'张三',
        age:18,
        gender: '男'
    }
  • 接口主要负责定义一个类的结构,接口可以去限制一个对象的接口:对象只有包含接口中定义的所有属性和方法时才能匹配接口;
  • 接口的作用类似于抽象类,不同点在于:接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法
interface myInter {
        name:string
        sayHello():void
    }
  • 同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性
interface myInter {
        name:string
        sayHello():void
    }
class MyClass implements myInter {
        name:string;
        constructor(name:string){
            this.name = name
        }
        sayHello(){
            console.log('hello');
        }
    }

八、属性的封装

对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装

默认情况下,对象的属性是可以任意的修改的,为了确保数据的安全性,在TS中可以对属性的权限进行设置

  • 静态属性(static)

    声明为static的属性或方法不再属于实例,而是属于类的属性;

  • 只读属性(readonly)

    如果在声明属性时添加一个readonly,则属性便成了只读属性无法修改

  • TS中属性具有三种修饰符

    • public(默认值),修饰的属性可以在任意位置访问(修改)
    • protected ,可以在当前类和当前类的子类中访问(修改)
    • private ,私有属性,只能在类内部进行访问(修改),可通过在类中添加方法使得私有属性可以被外部方法访问
      优势:掌控属性控制权,使代码更健壮,降低代码出错几率

示例:

public:

class Person{
    public name: string; // 写或什么都不写都是public
    public age: number;

    constructor(name: string, age: number){
        this.name = name; // 可以在类中修改
        this.age = age;
    }

    sayHello(){
        console.log(`大家好,我是${this.name}`);
    }
}

class Employee extends Person{
    constructor(name: string, age: number){
        super(name, age);
        this.name = name; //子类中可以修改
    }
}

const p = new Person('张三', 18);
p.name = '李四';// 可以通过对象修改

同时也可以直接将属性定义在构造函数中(语法糖):

class Person {
    constructor(public name: string, public age: number) {
    }
}

protected:

class C {
    protected num:number;
    constructor(num:number){
        this.num = num
    }
}
class D extends C {
    test(){
        console.log(this.num);
    }
}
const d = new D(18)
console.log(d.test()); //18
console.log(d.num); //报错,无法访问
d.num = 20 //报错,无法修改

private:

class Person {
        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(val:string){
            this.name = val;
        }
        //定义方法,用来获取age
        getAge(){
            return this.age
        }
        //定义方法,用来设置name
        setAge(val:number){
            if(val >= 20){
                this.age = val
            }
        }
    }
    const per = new Person('张三',18);
    
	console.log(per.name); //报错,无法访问
	console.log(per.age); //报错,无法访问
	
    console.log(per.getName()); //张三
    per.setName('李四');
    console.log(per.getName()); //李四

    console.log(per.getAge()); //18
    per.setAge(19) // <20
    console.log(per.getAge()); //18

    per.setAge(30) // >20
    console.log(per.getAge()); //30
class A {
    private num:number;
    constructor(num:number){
        this.num = num
    }
}
class B extends A {
    test(){
        console.log(this.num); //报错,不能访问
    }
}

九、属性存取器

  • 对于一些不希望被任意修改的属性,可以将其设置为private
  • 直接将其设置为private将导致无法再通过对象修改其中的属性
  • 我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
  • 读取属性的方法叫做setter方法,设置属性的方法叫做getter方法

示例:

class Person {
        private _name: string;
        private _age:number;
        constructor(name:string,age:number){
           this._name = name;
           this._age = age;
        }
//TS中设置getter方法的方法
   get name(){
       return this._name;
   }
//TS中设置setter方法的方法
   set name(val:string){
       this._name = val;
   }
   get age(){
       return this._age;
   }
   set age(val:number){
       if(val >= 20){
           this._age = val
       }
   }
    }
const per = new Person('张三',18);
console.log(per.name); //张三
per.name = "李四"
console.log(per.name); //李四

console.log(per.age); //18
per.age = 30
console.log(per.age); //30
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天内卷一点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值