TypeScript基础入门介绍(四)之类、接口篇

2020-02-17  本文已影响0人  大脸猫的前端之路

介绍

传统的JavaScript程序使用函数和基于原型的继承来创建面向对象的类,在es6中,JavaScript程序员能够使用基于类的面向对象的方式,通过引入class关键字,表示定义一个类。TypeScript中允许开发者使用这些特性。

类的定义

其实typescript中定义类的方法与ES6相同,在ES6的基础上,加了类型检查。

//es6中定义类的方法:
class Person {
     constructor(name){
        this.name = name;    
     }
     run() {
        console.log(this.name);
     }
}
//ts中定义类的方法
class Person {
    public name:string;    //  public关键字可省略
    constructor(name:string){   //构造函数   实例化类的时候触发的方法
        this.name = name;     
    }
    run():void {
        console.log(this.name);
    }
}
// 执行方法
var p=new Person('张三');
p.run()

继承

在TypeScript中,我们可以使用常用的面向对象模式。可使用继承(关键字extends、super)来扩展现有的类。

class Person {
    public name:string;    //  public关键字可省略
    constructor(name:string){   //构造函数   实例化类的时候触发的方法
        this.name = name;     
    }
    run():void {
        console.log(this.name);
    }
}
class Web extends Person{
    constructor(name:string){
        super(name);    // 初始化父类的构造函数,必须调用super();
    }
}
var w=new Web('张三');
w.run()

上述例子展示了基本的继承:类从基类中继承了属性和方法。这里, Web是一个派生类,它派生自Person基类,通过extends关键字。派生类通常被称作子类基类通常被称作超类.
因为Web继承了Person的功能,因此Web的实例能够执行run方法。

当子类中定义的方法和父类一致时,会执行子类中的方法,这是原型链的查找规则。

类中的修饰符(public、protected、private)

public :公有,在当前类里面、 子类 、类外面都可以访问;
protected:保护类型,在当前类里面、子类里面可以访问 ,在类外部没法访问
private :私有 ,在当前类里面可以访问,子类、类外部都没法访问

默认为public

在TypeScript中,成员默认为public,也可以明确将一个成员标记为public。上面的例子也可这么写:

class Person {
    public name:string;    //  public关键字可省略
    public constructor(name:string){   //构造函数   实例化类的时候触发的方法
        this.name = name;     
    }
    public run():void {
        console.log(this.name);
    }
}
var p=new Person('张三');
p.run()
理解protected

protected类型的成员在当前类和子类中都可以访问,但不能在类外部访问。

// 类外部无法访问保护类型的属性
class Person {
    protected name:string;    
    constructor(name:string){   
        this.name = name;     
    }
    run():void {
        console.log(this.name);
    }
}
class Web extends Person{
    constructor(name:string){
        super(name);   //  这里仍可以访问name,因为web是由person类派生来的
    }
}
var p=new Person('张三');
p.name;  //  error    不能在类外部使用protected类型变量或方法

注意:当派生类构造函数被标记为protected。这意味着这个类不能在包含它的类外被实例化,但是能被继承。

理解private

当成员被 标记成private时,它就不能在声明它的类的外部访问。

class Person {
    private name:string;    
    constructor(name:string){   
        this.name = name;     
    }
    run():void {
        console.log(this.name);
    }
}
class Web extends Person{
    constructor(name:string){
        super(name);   
    }
    work():void {
        console.log(this.name);  //  error  私有变量不能在子类中使用
    }
}
var p=new Person('张三');
p.name;  //  error  私有变量不能在类外部使用

静态属性 静态方法

静态属性及方法存在于类本身而不是类的实例上。使用static关键字定义,如果实例对象想访问静态属性,需在属性age前加类名Person,如下例:

class Person {
    name:string;    
    static age:number = 20;
    constructor(name:string){   
        this.name = name;     
    }
    static run():void {
        console.log(this.name);
    }
    work():void{ 
          console.log(Person.age);  //  访问静态属性,必须使用类Person调用
    }
}
var p = new Person('张三');
p.run();  //  error   访问静态方法,必须使用类调用
Person.run();   // right

抽象类 多态

抽象类作为其他派生类的基类,一般不会直接被实例化。使用abstract关键字定义抽象类和抽象方法。

抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。abstract抽象方法只能放在抽象类里面。

abstract class Animal{
    public name:string;
    constructor(name:string){
        this.name=name;
    }
    abstract eat():any;  //抽象方法不包含具体实现并且必须在派生类中实现。 
    run(){
        console.log('其他方法可以不实现')
    }
}
// var a=new Animal() /*错误的写法*/
class Dog extends Animal{
    //抽象类的子类必须实现抽象类里面的抽象方法
    constructor(name:any){
        super(name)
    }
    eat(){
        console.log(this.name+'吃粮食')
    }
}
var d=new Dog('小花花');
d.eat();

多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现。

 class Animal {
     name:string;
     constructor(name:string) {
         this.name=name;
     }
     eat(){   //具体吃什么  不知道 ?继承它的子类去实现 ,每一个子类的表现不一样
         console.log('吃的方法')
    }
}
class Dog extends Animal{
    constructor(name:string){
         super(name)
    }
   eat(){
       return this.name+'吃粮食'
   }
}
 class Cat extends Animal{
    constructor(name:string){
       super(name)
    }
    eat(){
      return this.name+'吃老鼠'
   }
}
var d = new Dog('小狗');
var c = new Cat('小花');
d.eat();  // 小狗吃粮食
c.eat();  //  小花吃老鼠
//  对于同一个方法每个子类实例有不同的表现

接口

接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescript中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。

属性类接口

ts中当自定义方法需对传入的参数进行约束时,我们可以这样定义:
约束传入的参数必须是对象,并且有label属性

function printLabel(labelInfo:{label:string}):void {
   console.log('printLabel');
}
printLabel('hahah'); //错误写法
printLabel({name:'张三'});  //错误的写法
printLabel({label:'张三'});  //正确的写法

当需要对批量方法传入的参数进行更新时,可引入接口:行为和动作的规范,对批量方法进行约束.

interface FullName{
     firstName:string;   //注意;结束
     secondName:string;
}
function printName(name:FullName){
     // 必须传入对象  firstName  secondName
    console.log(name.firstName+'--'+name.secondName);
}
printName('1213');  //错误
var obj={   /*传入的参数必须包含 firstName  secondName*/
     age:20,
     firstName:'张',
    secondName:'三'
};
printName(obj);   //  输出“张--三”

当接口里的属性不全都是必需的,在某些条件下存在,或者根本不存在时,可在可选属性名字定义的后面加?符号

函数类型接口

函数类型接口:对方法传入的参数以及返回值进行约束

interface encrypt {
  (key:string, value:string):string;
}
var md5:encrypt = function(key:string, value:string):string {
  return key+value;
}
console.log(md5('name', 'zhangsan'));

对于函数类型的类型检查来说,函数的参数名不需要与接口定义的名字相匹配,比如用下面的代码重写上面的例子:

var md5:encrypt = function(source:string, src:string):string {
  return source+src;
}

类类型接口

对类的约束,和抽象类有点相似
在C#或Java中,接口通常是用来定义一个类的公共部分,然后创建一个类,通过implements关键字去实现接口。

在接口中描述方法,在类里实现它。

interface Animal{
   name:string;
   eat(str:string):void;
}
class Dog implements Animal{
    name:string;
    constructor(name:string){
      this.name=name;
    }
    eat(){
      console.log(this.name+'吃粮食')
    }
}
var d=new Dog('小黑');
d.eat();

可索引接口

可索引接口:是对数组、对象的约束。不太常用

//可索引接口 对数组的约束
interface UserArr{   
  [index:number]:string
}
var arr:UserArr=['aaa','bbb'];
console.log(arr[0]);
var arr:UserArr=[123,'bbb'];  /*错误,索引的值只能是string*/
console.log(arr[0]);

 //可索引接口 对对象的约束
// 索引为string类型,值也为string类型
interface UserObj{
     [index:string]:string
}
var arr:UserObj={name:'张三'};

扩展接口:接口可以继承接口

interface Animal{
  eat():void;
}
interface Person extends Animal{
  work():void;
}
class Programmer{
    public name:string;
    constructor(name:string){
       this.name=name;
    } 
    coding(code:string){
        console.log(this.name+code)
    }
}
class Web extends Programmer implements Person{
     constructor(name:string){
         super(name)
     }
     eat(){
         console.log(this.name+'喜欢吃馒头')
     }
     work(){
      console.log(this.name+'写代码');
   } 
}
var w=new Web('小李');
w.eat();
w.coding('写ts代码');

在上面例子中,定义了两个接口AnimalPerson ,其中Person继承自Animal,又定义programmer类,具有name属性和coding方法,定义的Web类继承自Programmer并实现了Person接口,因此Web实例也有name属性和AnimalPerson接口的方法eat、work、coding

上一篇TypeScript基础入门(三)主要介绍ts中的函数

上一篇下一篇

猜你喜欢

热点阅读