ts随记:面向对象、泛型

啊啊啊啊啊真的会谢!和后端拿一个数据,问半天为什么要这个数据
言归正传!我!终于看懂了三年前没有学懂的面向对象了
ts是个好东西啊兄弟们

类:

  • 实例属性:直接定义,需要通过实例进行访问的
  • 类属性(静态属性):static 直接通过类访问
  • 只读属性:readonly 不能改
  • public(默认) :属性可以在任意位置访问(修改)
    private: 私有属性,只能在类内部进行访问修改,不被子类访问
    protect: 保护属性,只能在当前类和子类中使用
class Person{
    // 直接定义的为实例属性,要通过实例进行访问
    name: string = '孙悟空';
    // 在属性前使用static可以定义类属性(静态属性)
    static age: number = 18;
    // readonly:只读属性,不可修改
    readonly gender: number = 0;
    // 定义方法(使用static可以定义类方法)
    sayHello(){
        console.log("say hello");
    }
}

const per = new Person();
console.log(per);//Person {name: '孙悟空'}
console.log(Person.age);//18
// per.gender = 1;//报错

// 方法
per.sayHello()

构造函数:可以实现动态赋值

  • constructor:在创建对象时被调用
  • this:指向构建的对象的属性(class的属性)
class Dog{
    name = '旺财';
    age = 3;
    bark(){
        alert('wwww')
    }
    // 构造函数: 在创建对象时被调用
    constructor(name: string, age: number){
        // this指向构建的对象中的属性
        this.name = name,
        this.age = age
    }
}
const dog = new Dog("小黄", 1);
const dog1 = new Dog("小花", 2);
const dog2 = new Dog("大黄", 18);
console.log(dog);
console.log(dog1);
console.log(dog2);
//Dog {name: '小黄', age: 1}
//Dog {name: '小花', age: 2}
//Dog {name: '大黄', age: 18}

继承: 将几个拥有共同属性,共同方法(功能)的类合并在一起,只写一次,再进行个性化修改

  • 子类中写父类的方法名的方法,叫做重写
  • super为父类对象,可以获取父类的属性方法等
  • 当子类有新增的属性,需要用到constructor进行构造,此时需要引入父类的属性
(function(){
    class Animal{
        name: string | undefined;
        age: number | undefined;

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

        sayHello(){
            console.log('父类:动物在叫');
        }
    }
    // extends: 继承
    // 子类(Dog)继承父类(Animal)
    // 子类拥有父类所有的方法和属性
    // 作用:将多个类中共有的代码统一写在父类中
    //super为父类对象
    class Dog extends Animal{
        gender: number | undefined;
        constructor(name: string, age: number, gender: number){
            super(name, age);
            this.gender = gender;
        }
        run(){//属于当前子类自己的方法
            console.log(`${this.name}在跑`);
        }
        sayHello() {//重写父类方法
            console.log('子类:狗子叫');
            super.sayHello();
        }
    }

    const dog = new Dog('狗子', 5, 0)
    console.log(dog);
    dog.sayHello();
    dog.run();
})()

抽象类:父类不能被直接使用,是一个抽象化的存在,没有实质性的功能,只能被继承

  • abstract :不能用于创建实例,只能被继承
  • 抽象类中可以定义抽象方法,继承者必须重写该方法
(function(){
    // abstract :抽象类
    // 不能用于创建对象(new CLASS())
    // 只是用来被继承(只能当爸爸)
    abstract class Animal{
        name: string | undefined;
        age: number | undefined;

        constructor(name: string, age: number){
            this.name = name;
            this.age = age;
        }
        // 可以添加抽象方法 ,同样只能被重写,不能直接被调用
        // 只能被定义在抽象类中
        // 继承类者必须重写改方法
        abstract sayHello():void;
    }
    class Dog extends Animal{
        sayHello() {
            console.log('子类:狗子叫');
        }
    }

    const dog = new Dog('狗子', 5)
    console.log(dog);
    dog.sayHello();
})()

接口:用来定义一个类的规范(模板),是一种规范化的存在

  • 可以多次定义,最终进行合并(???有点怪,感觉有坑)
  • 里面的所有属性没有实际的值(函数==抽象函数)
(function(){
    type myType = {
        name: string,
        age: number
    }

    // 接口:用来定义一个类的规范(模板)
    // 可以多次定义,最终进行合并(???有点怪,感觉有坑)
    interface myInterface{
        name: string,
        age: number
    }
    interface myInterface{
        gender: number
    }
    const obj: myInterface = {
        name: '11',
        age: 88,
        gender: 0
    }
    // 接口可以限制类的结构
    // 里面的所有属性没有实际的值(函数==抽象函数)
    interface MyInter{
        name: string;
        sayHello():void;
    }
    class MyClass implements MyInter{
        name: string;
        constructor(name: string){
            this.name = name;
        }
        sayHello(){
            console.log("大家好");
            
        }
    }
})()

属性封装:可以做到拦截修改,提高安全性

  • ts中自己封装了getter和setter的方法,在需要进行修改拦截(年龄问题)的情况下可以进行使用
(function(){
    class Person{
        // public(默认) :属性可以在任意位置访问(修改)
        // private: 私有属性,只能在类内部进行访问修改,可以做到拦截修改(set,get)
        // - 私有熟悉不被子类访问
        // protect: 保护属性,只能在当前类和子类中使用
        private _name: string;
        private _age: number;
        constructor(name:string, age: number){
            this._name= name;
            this._age = age;
        }
        get age(){
            return this._age;
        }
        //=================原理
        // getAge(){
        //     return this._age;
        // }
        set age(value: number){
            if(value < 0 || value > 200){
                throw new Error("age不合法");
            }
            this._age = value
        }
        //==================原理
        // setAge(value:number){
        //     if(value < 0 || value > 200){
        //         throw new Error("age不合法");
        //     }
        //     this._age = value;
        // }
    }

    const per = new Person('孙悟空', 18);
    per.age = 100
    console.log(per.age);//100
})()

泛型:对不确定类型的参数进行变量定义,调用时再指定

// 定义函数/类时,遇到类型不明确时可以使用泛型
// T为类型的变量,调用时才赋值
function fn<T>(a:T): T{
    return a;
}
console.log(fn(10));//不指定泛型,TS自动对类型进行推断
console.log(fn<string>('hello'));//指定泛型

function fn2<T,K>(a:T, b:K):T{
    console.log(b);
    return a;
}
interface Inter{
    length: number;
}
// T 要实现Inter接口(拥有length属性:字符串、obj.length)
function fn3<T extends Inter>(a: T): number{
    return a.length;
}
fn3('123');
fn3({length: 7})

我第一次接触ts,因为不理解ts使用的意义比如说接口,结果全程把ts当js写
其实对于ts的意义,在学习理解了面向对象的思想之后,倒是有点清楚了。
到最后老师说了,这个东西并不是说一定要用,但是他是一种规范,一种思想。
虽然有些配置和操作确实比起js来说复杂不少,但是不得不说,统一开发规范可见地会大大地有利于后期维护以及多人的合作开发
如果你还是有点不理解ts到底用来干嘛,建议花点时间看看这几个视频

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值