TS语法四 类

TS中的类:

  • 创建类实例
  • constructor方法
  • 取值函数和存值函数
  • class表达式
  • 静态方法
  • 实例属性其他写法
  • 实现私有方法

ES5中创建类实例

function Point(x, y){
    
    
    this.x = x
    this.y= y
}

Point.prototype.getPosition = function(){
    
    
    return '(' + this.x + ' , ' + this.y +')'
}

var p1 =  new Point(2,3)
console.log(p1.getPosition())  //(2 , 3)

ES6中创建实例

class Point1 {
    
    
    x: number
    y: number
    constructor(x, y) {
    
    
        this.x = x
        this.y = y
    } 
    getPosition() {
    
    
        return '(' + this.x + ' , ' + this.y +')'
    }
}

const p2 = new Point1(2,3)
console.log(p2.getPosition())  //(2 , 3)

ES5中的取值函数和存值函数

var userInfo = {
    
    
    _age: 18,
    set age(newValue){
    
    
        if(newValue>18){
    
    
            console.log('年纪很大了')
        }else{
    
    
            console.log('还年轻,哈哈')
        }
    },
    get age(){
    
    
        console.log('年纪是---')
        return this._age
    }
}
console.log(userInfo.age)   //年纪是---  18
userInfo.age = 16   //还年轻,哈哈

ES6中的取值和存值函数

class userInfo1 {
    
    
    _age:number
    constructor(age){
    
    
        this._age = age
    }
    set age(newValue){
    
    
        if(newValue>18){
    
    
            console.log('年纪是---')
        }else{
    
    
            console.log('还年轻,年纪是---')
        }
    }
    get age(){
    
    
        console.log('获得的年纪是---')
        return this._age
    }
}
const userInfo2 = new userInfo1(18)
console.log(userInfo2.age)  //获得的年纪是---  18
userInfo2.age = 20  //年纪是---

//class的另一种写法
const class1 = class c {
    
    
    constructor(){
    
    }
}
const class2 = new class1()

静态方法和静态属性

class Point2 {
    
    
    x: number
    y: number
    static z:number = 10
    constructor(x, y) {
    
    
        this.x = x
        this.y = y
        console.log('target---',new.target)
    } 
    getPosition() {
    
    
        return '(' + this.x + ' , ' + this.y +')'
    }
    static getClassName(){
    
    
        return Point2.name    //es5中的方法,可以直接返回类的名称
    }
}
const point3 = new Point2(2,4)     //初始化时可以拿到target里的信息,如下:
// target--- class {
    
    
//     constructor(x, y) {
    
    
//       this.x = x;
//       this.y = y;
//       console.log("target---", new.target);
//     }
//     getPosition() {
    
    
//       return "(" + this.x + " , " + this.y + ")";
//     }
//     static getClassName() {
    
    
//    …

// console.log(point3.getClassName())  //这样写会报错
console.log(Point2.getClassName())  //_Point2
console.log(Point2.z) //10

ES5中的类的继承

function Food(){
    
    
    this.type = 'food'
}
Food.prototype.getType = function(){
    
    
    return this.type
}

function Vegetable(name){
    
    
    this.name = name
}
Vegetable.prototype = new Food()

const tomato2 = new Vegetable('tomato')
console.log(tomato2.getType())   //food

ES6中的继承

class Parent {
    
    
    name: string
    constructor(name){
    
    
        this.name = name
    }
    getName(){
    
    
        return this.name
    }
    static getNames(){
    
    
        return this.name
    }
}

class Child extends Parent{
    
    
    age:number
    constructor(name,age){
    
    
        super(name)
        this.age = age
    }
}

const child1 = new Child('lyy',18)
console.log(child1)
console.log(child1.getName())  //lyy
console.log(child1 instanceof Child)  //true
console.log(child1 instanceof Parent)  //true
console.log(Child.getNames())   //Child

关于super

1.super作为函数,ES6中要求,子类中构造函数必须调用一次super()函数
2.super作为对象,在普通方法中指向父类的原型对象,在静态方法中指向父类

class Parent1{
    
    
    type: string
    static getType: () => string
    constructor(){
    
    
        this.type = 'parent'
    }
    getName(){
    
    
        return this.type
    }
}
Parent1.getType = () => {
    
    
    return 'is parent'
}

class Child1 extends Parent1{
    
    
    constructor(){
    
    
        super()
        console.log('constructor:'+super.getName())
    }
    getParentName(){
    
    
        console.log('getParentName:'+super.getName())
    }
    static getParentType(){
    
    
        console.log('getParentType:'+super.getType())
    }
}

const c1 = new Child1()  //constructor:parent
c1.getParentName()  //getParentName:parent
Child1.getParentType()  //getParentType:is parent

//如果在子类里对同样的数据进行赋值,看一下效果
class Child2 extends Parent1{
    
    
    constructor(){
    
    
        super()
        console.log('constructor:'+super.getName())
        this.type = 'lyy'
    }
    getParentName(){
    
    
        console.log('getParentName:'+super.getName())
    }
    static getParentType(){
    
    
        console.log('getParentType:'+super.getType())
    }
}

const c2 = new Child2()  //constructor:parent
c2.getParentName()  //getParentName:lyy
Child1.getParentType()  //getParentType:is parent

//原生函数的继承(ES6中可以)。原生函数包括:Boolean, Number, String, Array, Date, Function, RegExp, Error, Object
class CustomArray extends Array {
    
    
    constructor(...args){
    
    
        super(...args)
    }
}

const array1 = new CustomArray(3)
array1.fill(3)
console.log(array1)  //CustomArray(3) [3, 3, 3]

注意:
ES6的类和ES5的构造函数,这两种形式在实现继承的机制上存在差异。
ES5继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上;
而ES6的继承是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后才可以使用this关键字,否则报错。

TS中的类:

//ts中的语法
class Point3 {
    
    
    public x: number
    public y: number
    constructor(x:number, y:number) {
    
    
        this.x = x
        this.y = y
    } 
    getPosition() {
    
    
        return '(' + this.x + ' , ' + this.y +')'
    }
}

修饰符(public, private, protected)

//private
class Parent2 {
    
    
    private age: number
    constructor(age: number){
    
    
        this.age = age
    }
}

const p = new Parent2(18)
// p.age    报错,只能在Parent2内部使用

class child2 extends Parent2{
    
    
    constructor(age: number){
    
    
        super(age)
        // console.log(super.age)  报错,这里不能访问父类的私有属性
    }
}

//protected
class Parent3 {
    
    
    protected age: number
    constructor(age: number){
    
    
        this.age = age
    }
    protected getAge() {
    
    
        return this.age
    }
}

const p3 = new Parent3(18)
// p3.age  报错,只能在Parent3内部以及子类中使用
class child3 extends Parent3 {
    
    
    constructor(age: number) {
    
    
        super(age)
        console.log('Parent3',super.age)  //子类中不能直接访问父类的protected属性,但是可以访问protected方法
        console.log('Parent3 method',super.getAge())
    }
}

const child4= new child3(20)  
//Parent3 undefined   
//Parent3 method 20

父类的构造方法中如果添加了protected,如下:

class Parent3 {
    
    
    protected age: number
    protected constructor(age: number){
    
    
        this.age = age
    }
    protected getAge() {
    
    
        return this.age
    }
}

// const p3 = new Parent3(18)  这里会报错

此时就不能直接通过父类的构造函数生成实例了,只能通过子类的构造函数生成实例

只读属性readonly

class UserInfo3 {
    
    
    readonly name: string
    constructor(name: string){
    
    
        this.name = name
    }
}

const userInfo4 = new UserInfo3('lyy')
// userInfo4.name = 'lllll'  报错,readonly属性不可修改

静态属性static

class Parent4 {
    
    
    public static getAge(){
    
    
        return Parent4.age
    }
    private static age: number = 180
    constructor(){
    
    }
}

const p4 = new Parent4()
console.log(Parent4.getAge())  //只能在通过父类访问

可选属性

class userInfo {
    
    
    public name: string
    public age?: number
    constructor(name: string, age?: number, public sex?: string){
    
    
        this.name = name
        this.age = age
    }
}
const info1 = new userInfo('lyy')  
console.log(info1). //userInfo {sex: undefined, name: 'lyy', age: undefined}

存取属性

class userInfo2 {
    
    
    private _address: string
    constructor(){
    
    }
    get address() {
    
    
        return this._address
    }
    set address(value){
    
    
        this._address = value
    }
}

const info2 = new userInfo2()
info2.address='asdg'
console.log(info2.address)  //asdg

抽象类

abstract class People {
    
    
    constructor(public name: string) {
    
    }
    public abstract printName(): void
}

class Man extends People{
    
    
    constructor(name: string){
    
    
        super(name)
        this.name = name
    }
    public printName() {
    
    
        console.log(this.name)
    }
}

const m1 = new Man('lyy')
m1.printName()   //lyy

//使用abstract标记属性和存取器
abstract class People1 {
    
    
    abstract _name: string
    abstract get name(): string
    abstract set name(value: string)
}

class Man1 extends People1{
    
    
    _name: string
    get name(): string {
    
    
        return this._name
    }
    set name(value: string) {
    
    
        this._name = value
    }
}

类可以多次赋值不同的类型

class People2 {
    
    
    constructor(public name: string){
    
    }
}
class Animal {
    
    
    constructor(public name: string){
    
    }
}
let p1:People2 = new People2('people')
p1 = new Animal('animal')
//所以要用instanceof判断类的类型,因为一个类可以多次赋值不同的类型

//接口的实现
interface Food {
    
    
    type: string
    name: string
}

class FoodInfo implements Food{
    
    
    type: string
    name: string
}

注意:
接口继承类,会继承这个类的成员但是不包括其实现,也就是说只继承这个成员及其类型。接口还会继承private和protected修饰的成员,当接口继承的类中包含这两个修饰符修饰的成员变量时,该变量只能被这个类以及子类实现

class A {
    
    
    protected name: string
}
interface I extends A {
    
    }
class B implements I {
    
    
    public name: string     // 这里有name属性依然会报错,因为B必须要继承A
}
class C extends A implements I {
    
    
    public name: string   // 直接继承就可以
}

泛型中使用类类型

// 这里的new()表示调用这个类的构造函数,返回的类型即创建的实例的类型
const create = <T>(c: new() => T): T =>{
    
    
    return new c()
}

class Infos {
    
    
    public age: number
    constructor(){
    
    
        this.age = 18
    }
}

console.log(create(Infos)) //Infos {age: 18}
console.log(create(Infos).age)    //18

猜你喜欢

转载自blog.csdn.net/LittleMoon_lyy/article/details/124215500
今日推荐