【TypeScript】第四部分 面向对象

导读:本篇文章讲解 【TypeScript】第四部分 面向对象,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

【TypeScript】第四部分 面向对象



4. 面向对象

4.1 什么是对象

  • 举例来说:
    • 操作浏览器要使用window对象
    • 操作网页要使用document对象
    • 操作控制台要使用console对象

一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是什么,计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人、一条狗、一把枪、一颗子弹等等所有的事物。一个事物到了程序中就变成了一个对象。

在程序中所有的对象都被分成了两个部分数据和功能以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能。数据在对象中被成为属性,而功能就被称为方法。所以简而言之,在程序中一切皆是对象。

4.2 类(class)

要想面向对象,操作对象,首先便要拥有对象,那么下一个问题就是如何创建对象。要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象

/* 
    用class关键字定义了一个Person类
    对象主要包括两个部分:
        属性
        方法
*/
class Person{
    /*
        直接定义属性是实例属性,需要通过对象的实例去访问
    */
    name = 'jack'
    age = 18

    /* 
        在属性的前使用static关键字可以去定义属性为静态属性(类属性)
        该属性只能由类去访问
    */
    static hello = '你好'

    // 方法也是如此,直接写是由实例对象去访问,加了static关键字由类去访问
    sayhello(){
        console.log('大家好!!')
    }

    static sayhello1(){
        console.log('我是静态方法')
    }
}

// 实例化对象
const p = new Person();
console.log(p.name)
console.log(Person.hello)
p.sayhello()
Person.sayhello1()

4.3 构造函数和this

class Dog{
    name:string
    age:number
    // constructor 被称为构造函数
    // 构造函数会在对象创建时进行调用
    // this指向当前创建的实例化对象
    constructor(name:string,age:number){
        this.name = name
        this.age = age

    }
    bark(){
        console.log('汪汪汪',this)
    }
}

new Dog('旺财',2)
new Dog('小黑',2)
console.log(new Dog('旺财',2))
console.log(new Dog('小黑',2))

const d = new Dog('jack',4) 
d.bark() // this指向jack

4.4 继承和重写

class Animal{
    name:string
    age:number
    constructor(name:string,age:number){
        this.name = name
        this.age = age
    }

    sayhello(){
        console.log('动物在叫~~~')
    }
}

/*
    extends 关键字用来继承父类
        - 继承后子类将会拥有父类所有的方法和属性
        - 继承用于:将多个类中共同的代码写在一个父类当中,这样可以
        - 减少代码的重复性
        - 在子类中可以添加自己独有的属性和方法
        - 如果子类在添加了和父类相同的方法,则子类可以覆盖父类的方法
          这种形式我们称为重写
*/
class Cat extends Animal{
    run(){
        console.log('咻咻咻')
    }
    sayhello(): void {
        console.log('我是小猫')
    }
}

class Mounse extends Animal{
    eat(){
        console.log('叽叽叽')
    }
    sayhello(): void {
        console.log('我是老鼠')
    }

}

const cat = new Cat('小七',2)
cat.sayhello()
cat.run()

const mouse = new Mounse('汤姆',5)
mouse.sayhello()
mouse.eat()


4.5 super关键字

class Animal1{
    name:string
    constructor(name:string){
        this.name = name
    }
    sayhello(){
        console.log('我是动物')
    }
}

class Rabbit extends Animal1{
    say(){
        //在类方法中,super就相当于当前类的父类
        super.sayhello()
    }
}

const r = new Rabbit('小白')
r.say()

/* 
    当我们想要在子类上添加新的属性时候会发现问题
    之前我们说过在子类上写相同的函数会被重写
    这时候就需要使用super()去调用父类
*/

class Fish extends Animal1{
    age:number
    // 在子类写构造函数,就必须要调用父类的构造函数
    constructor(name:string,age:number){
        super(name) // 这个代码的意思是:调用父类的构造函数
        this.age = age
    }
    sayhello(): void {
        console.log('我是鱼')
    }
}

const f = new Fish('喜喜',2)
f.sayhello()

4.6 抽象类

//抽象类和其他类的区别就是抽象类不能用来创建对象
//抽象类就是为了给其他类继承用的
abstract class Person1{
    name:string
    age:number

    constructor(name:string,age:number){
        this.name = name
        this.age = age  
    }

    // 定义抽象方法,没有具体的方法体
    // 抽象方法只能被定义在抽象类中,子类继承后必须要重写该方法
    abstract sayGoodBye():void
}

class Jack extends Person1{
    gender:string
    constructor(name:string,age:number,gender:string){
        super(name,age)
        this.gender = gender
    }

    sayGoodBye(): void {
        console.log('bye bye')
    }
}
const j = new  Jack('丽华',12,'女')
j.sayGoodBye()

4.7 接口

接口的作用类似于抽象类不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法(抽象类可以有其他方法和抽象方法)。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。

// 定义一个接口
interface botany{
    name:string
    flowerPhase:string
    message():void
}
/* 
    定义类的时候可以使得类去实现一个接口
    实现接口就是使类能够去满足接口的要求
*/
// 实现接口
class Rose implements botany{
    name: string
    flowerPhase: string
    constructor(name:string,flowerPhase:string){
        this.name = name
        this.flowerPhase = flowerPhase
    }
    message(): void {
        console.log(`我是${this.name},花期为${this.flowerPhase}`)
    }
}

const rose = new Rose('玫瑰花','五个月')
rose.message()

4.8 属性的封装

TS可以在属性前添加修饰符

  1. public
    • 修饰的属性可以在任意位置访问/修改 默认值
  2. private
    • 私有属性 私有属性只能在该类内部进行访问/修改
      因为设置了私有属性,所以只能由该类进行访问/修改
      这时候我们可以通过定义方法将属性抛出,这样我们就可以
      对属性做一些操作,比如:在修改年龄的时候加限制条件
  3. protected
    • 可以在该类和子类中进行访问/修改,实例对象无法进行访问/修改
class Person2{
    private _name:string
    private _age:number
    protected _gender:string
    constructor(name:string,age:number,gender:string){
        this._name = name
        this._age = age
        this._gender = gender
    }

    /* 
        将getname和setname这种设置属性的方法称作为属性的存取器
    */
    getage(){
        return this._age
    }
    setage(value:number){
        if(value >0)
        {
            this._age = value
        }     
    }

    /* 
        在TS中我们可以使用TS所提供的语法糖
        语法:
            get 方法名(){retun }
            set 方法名(value:type){} 
        使用的时候就和平常访问修改一样
    */
    get name(){
            return this._name
    }    

    set name(value:string){
            this._name = value
    }
    
}

class A extends Person2{
    test(){
       // 子类可以访问
        console.log(this._gender)
    }
}
const a = new A('mark',18,'female')
a.test()  //

const p2 = new Person2('jack',12,'male')
console.log(p2.getage())  //12
p2.setage(33)  //33

// 使用的时候就和平常一样
console.log(p2.name)
p2.name = 'mark'

console.log(p2)



4.9 泛型

定义一个函数或者是类的时候,有些情况是无法确定要使用的类型(返回值 、参数、属性的类型),这个时候就可以使用泛型.

/*
    
 */
function f1<T>(a:T):T{
    return a
}
//当我们在调用时,如果不指定泛型TS会帮我们自动去推断类型
f1('hello') //此时泛型的值string

//当我们的代码很复杂时,TS不一定能够准确推断出类型
f1<number>(2222) //手动去指定泛型,能够更好的避免出错

// 可以指定多个泛型
class C<A,K>{
        name:A
        age:K
        constructor(name:A,age:K){
            this.name = name
            this.age = age
        }
}

const c = new C<string,number>('jack',18)


interface inter {
   length:number
}
// 表示F必须是inter的实现类
function fn2 <F extends inter>(a:F):number{
    return a.length
}
// 传进来的参数必须要有length这个属性
console.log(fn2('你好')) // 2


总结

以上就是今天要讲的内容,希望对大家有所帮助!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82903.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!