typescript中的类和es5中的类

es5中定义一个类

简单的类

//最简单的类
function People(){ this.name="张三", this.age=20 } var p=new People(); console.log(p.name)

构造函数和原型链里面增加方法

//构造函数和原型链里面增加方法
function People(){
    this.name="张三", //属性
    this.age=20,
    this.fun=function(){
        console.log(this.age)
    }
}
//原型链的属性会被多个实例共享,构造函数中的不会 People.prototype.work=function(){ console.log(this.name+"在学习") } var p=new People(); p.fun() p.work()

类中的静态方法

//类中的静态方法
function People(){
    this.name="张三", //属性
    this.age=20,
    this.fun=function(){     //实例方法
        console.log(this.age)
    }
}
People.getInfo=function(){
    //不需要实例化,直接通过类.方法调用
    console.log("我是静态方法")
}
People.getInfo()

 

 

es5中的继承

 对象冒充实现继承

// es5中的继承
function People(){
    this.name="张三", //属性
    this.age=20,
    this.fun=function(){     //实例方法
        console.log(this.age)
    }
}
People.prototype.work=function(){
    console.log(this.name+"在学习")
}
//web类,继承People类  ,  原型链+对象冒充的组合继承模式
function Web(){
         //对象冒充实现继承
        People.call(this)
}
var w =new Web();
w.fun()    //对象冒充可以继承构造函数里面的属性和方法

 

 但是如果要调用work方法就会报错

 

 注意:对象冒充可以继承函数里面的属性和方法,但是没法继承原型链中的属性和方法

原型链继承

function People(){
    this.name="张三", //属性
    this.age=20,
    this.fun=function(){     //实例方法
        console.log(this.age)
    }
}
People.prototype.work=function(){
    console.log(this.name+"在学习")
}
//web类,继承People类  ,  原型链+对象冒充的组合继承模式
function Web(){
    
}
//原型链继承
Web.prototype=new People();
var w =new Web();
w.fun()   //对象冒充可以继承构造函数里面的属性和方法
w.work()

 

 原型链继承既可以继承构造函数中的属性和方法,也可以继承原型链中的属性和方法

原型链继承中的问题

首先我们看下面的案例

//原型链继承中的问题
function People(name,age){
    this.name=name, //属性
    this.age=age,
    this.fun=function(){     //实例方法
        console.log(this.name)
    }
}
People.prototype.work=function(){
    console.log(this.name+"在学习")
}
//web类,继承People类  ,  原型链+对象冒充的组合继承模式
function Web(name,age){
    
}
//问题出现了
Web.prototype=new People();
var w=new Web("赵四",18)
var w1=new Web("王五",13)
w.fun()

此时运行我们可以看输出为undefined

 

 这是因为实例化子类的时候没法给父类传参

原型链+构造函数的组合继承模式

//原型链+构造函数的组合继承模式
function People(name,age){
    this.name=name, //属性
    this.age=age,
    this.fun=function(){     //实例方法
        console.log(this.name)
    }
}
People.prototype.work=function(){
    console.log(this.name+"在学习")
}
//web类,继承People类  ,  原型链+对象冒充的组合继承模式
function Web(name,age){
    People.call(this,name,age)  //对象冒充继承,实例化子类可以给父类传参
}
//问题出现了
Web.prototype=new People();
var w=new Web("赵四",18)  //实例化子类的时候没法给父类传参
w.fun()

原型链+构造函数的组合继承模式l另一种方法

//原型链+构造函数的组合继承模式l另一种方法
function People(name,age){
    this.name=name, //属性
    this.age=age,
    this.fun=function(){     //实例方法
        console.log(this.name)
    }
}
People.prototype.work=function(){
    console.log(this.name+"在学习")
}
//web类,继承People类  ,  原型链+对象冒充的组合继承模式
function Web(name,age){
    People.call(this,name,age)  //对象冒充继承,可以继承构造函数里面的属性和方法,实例化子类可以给父类传参
}
//问题出现了
Web.prototype= People.prototype;
var w=new Web("赵四",18)  //实例化子类的时候没法给父类传参
w.fun()

ts中类的定义

我们接下来看在ts中类的使用

// ts中类的定义
class Person{
    name:string;  //属性,前面省略的public关键词
    constructor(n:string){  //构造函数,实例化类的时候触发的方法
        this.name=n;
    }
    fun():void{
        console.log(this.name)
    }
}
var p=new Person("小明");
p.fun()

我们看一下编译之后的js文件

 

 我们再来看一下ts中的set和get方法

class Person{
    name:string;  //属性,前面省略的public关键词
    constructor(name:string){  //构造函数,实例化类的时候触发的方法
        this.name=name;
    }
    getName():string{
        return this.name
    }
    setName(name:string):void{
        this.name=name
    }
}
var p=new Person("小明");
console.log(p.getName())
p.setName("小红")
console.log(p.getName());

我们看一下编译之后的js文件

 

ts中的继承

在ts中通过extends和super实现继承

//ts中实现继承  extends  super
class Person{
    name:string;
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
var p= new Person("小明");
console.log(p.fun())

编译后的js文件

 ts继承:父类方法和子类方法一致

class Person{
    name:string;
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
class Web extends Person{
    constructor(name:string){
            super(name)    //初始化父类的构造函数
    }
}
var w=new Web("李四")
console.log(w.fun())

编译后的js文件

 ts继承:父类方法和子类方法不一致

 我们在Web类中添加一个方法然后再调用

class Web extends Person{
    constructor(name:string){
            super(name)   //初始化父类的构造函数
    }
    work(){
        console.log(`${this.name}学习`)
    }
}
w.work()
 

编译后的js文件

 

 如果我们子类中也有一个方法跟父类中的方法一样

 fun():string{
        return `${this.name}在打游戏`
    }

我们看一下输出结果

 

 

 父类和子类有同样的方法的时候,调用子类的方法时,首先在子类中找,如果子类中没有在去父类中找

ts类中的修饰符

ts中定义属性的时候提供了三种修饰符:

  • public:公有,(在类里面,子类,类外面都可以访问)
  • protected:保护类型,(在类里面,子类可以访问,在类外面没法访问)
  • private:私有,(在类里面可以访问,子类和类外面没法访问)

属性如果不加修饰符默认为public

1.public

 我们看下面的案例

public:公有,(在类里面,子类,类外面都可以访问)
class Person{
    public name:string;   //公有属性
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
class Web extends Person{
    constructor(name:string){
            super(name)   //初始化父类的构造函数
    }
    work(){
        console.log(`${this.name}学习`)
    }
    fun():string{
        return `${this.name}在打游戏`
    }
}
var w=new Web("李四")
w.work()

//类外部访问公有属性
var p=new Person("老王")
console.log(p.name)

 

 我们可以看到属性如果为public,那么在类中,子类,类外面都可以访问这个属性

 2.protected

//protected:保护类型,(在类里面,子类可以访问,在类外面没法访问)
class Person{
    protected name:string;   //公有属性
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
class Web extends Person{
    constructor(name:string){
            super(name)   //初始化父类的构造函数
    }
    work(){
        console.log(`${this.name}学习`)
    }
}
var w=new Web("李四")
w.work()
console.log(w.fun())

 

 此时我们可以看到在子类中可以正常访问

但是当我们在外部访问属性时:

//类外部访问公有属性
var p=new Person("老王")
console.log(p.name)

我们看一下编译后的js文件

 

 此时ts编译会报错,但是浏览器会输出结果,这是因为把tsclass语法转义成了js,所以能够运行

 

 

 

 

 3.private

 

//private:私有,(在类里面可以访问,子类和类外面没法访问)
class Person{
    private name:string;   //公有属性
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
class Web extends Person{
    constructor(name:string){
            super(name)   //初始化父类的构造函数
    }
    work(){
        console.log(`${this.name}学习`)
    }
}
var p=new Person("李四")
console.log(p.fun())
var w=new Web("李四")
w.work()
console.log(w.work())

此时我们在终端可以看到报错,不论在子类中使用,还是在外类中使用都会报错

 

 此时我们在类中使用

//private:私有,(在类里面可以访问,子类和类外面没法访问)
class Person{
    private name:string;   //公有属性
    constructor(name:string){
        this.name=name
    }
    fun():string{
        return `${this.name}在写作业`
    }
}
class Web extends Person{
    constructor(name:string){
            super(name)   //初始化父类的构造函数
    }
}
var p=new Person("李四")
console.log(p.fun())

此时不会报错,可以看到浏览器输出

 ts中的静态属性和静态方法

class Person{
    name:string
    constructor(name:string){
        this.name=name
    }
    fun(){     //实例方法
        console.log(`${this.name}在学习`)
    }
    work(){     //实例方法
        console.log(`${this.name}在工作`)
    }
    static play(){       //在方法的前面加上一个static即为静态方法
        console.log("静态方法")
    }

}
//实例化调用实例方法
var p=new Person("小明")
p.fun();

//静态方法调用
Person.play()

编译后的ejs文件

 

 但是静态方法不能直接调用类中的属性

此时我们在静态方法中输出age属性

public age:string=20
......
 static play(){
        console.log("静态方法",this.age)
    }

结果返回的结果是undefined

 

 如果我们想要获取这个属性

就需要把这个属性改为静态属性,在属性名前加上static关键字

static age:number=20
 static play(){
        console.log("静态方法",Person.age)
        console.log("静态方法",this.age)
    }            

这两种方法都可以获取静态属性

 

 多态

父类定义一个方法不去实现,让继承他的子类去实现,每一个子类有不同的表现

多态也是继承的一种表现,

class Animal{
    name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(){     //具体吃什么不知道 具体吃什么,让继承的子类实现,每一个类的表现不一样
        console.log("吃的方法")
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name);
    }
    eat(){
        console.log( this.name+"吃肉")
    }
}
class Cat extends Animal{
    constructor(name:string){
        super(name);
    }
    eat(){
        console.log( this.name+"老鼠")
    }
}
var dog= new Dog("大黄")
dog.eat()
var cat= new Cat("橘猫")
cat.eat()

我们看一下编译之后的js文件

 

 抽象方法

 ts中的抽象类,它是由其他类继承的基类,不能直接被实例化

用abstract关键字定义的抽象类的和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现

abstract抽象方法只能放在抽象类里面

抽象类和抽象方法用来定义标准,标准就是Animal这个类要求他的子类必须包含eat方法

我们看下面的代码

abstract class Animal{
      abstract eat():any;
    }

var a =new Animal()

抽象方法放在抽象类中

但是不能实例化这个类

此时就会报错

 

 

 

 案例:

abstract class Animal{
    name:string;
    constructor(name:string){
        this.name=name
    }
      abstract eat():any;
    }

class Dog extends Animal{
    constructor(name:string){
        super(name);
    }
    //抽象类的子类必须实现抽象类中的方法
    eat(){
        console.log(`${this.name}吃肉`)
    }
}
var d=new Dog("大黄")
d.eat()

编译后的js文件

 

 

 此时我们在定义一个Cat类,继承Animal类但不会实现Animal中的eat方法

class Cat extends Animal{
    constructor(name:string){
        super(name);
    }
    fun(){
        console.log(`${this.name}吃肉`)
    }
}

 此时就会报错

 

 如果继承抽象类,就必须实现抽象父类中的方法

 

posted @ 2021-11-04 10:51  keyeking  阅读(105)  评论(0编辑  收藏  举报