zoukankan      html  css  js  c++  java
  • 13.typescript-类

    晚上睡不着 早上睡不着 中午睡不着 想睡觉

    <----------------------------------------☺mizhiweixiao☺---------------------------------------->

    1.类的相关概念

    (1)类(Class):定义了一件事物的抽象特点,包含它的属性和方法。

    (2)对象(Object):类的实例,通过new生成。

    (3)面向对象(OOP)的三大特性:封装,继承,多态。

    (4)封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据。

    (5)继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。

    (6)多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。

    比如:Cat和Dog都继承自Animal,但是分别实现了自己的eat方法。此时针对某一个实例,我们无需了解它是Cat还是Dog,就可以直接调用eat方法,程序会自动判断出来应该如何执行eat。

    (7)存取器(getter&setter):用以改变属性的读取和赋值行为。

    (8)修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。

    比如public表示公有属性或方法。

    (9)抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中实现。

    (10)接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类智能继承自另一个类,但是可以实现多个接口。

    2.类

    举个栗子

     1 // 声明一个Students类(首字母大写):这个类里面有三个成员
     2 class Students{
     3     // 一个name属性
     4     name : string;
     5     // 一个构造函数
     6     constructor(message:string){
     7         this.name = message;
     8     };
     9     // 一个sayHi方法发
    10     sayHi(){
    11         return "Hi "+this.name;
    12     };
    13 
    14 }
    15 
    16 // 构造了Students类的一个实例
    17 var getStu = new Students("weizeyang");

    下面我们来解剖下上面的代码

    (1)使用class关键字声明类,且类的首字母大写

    (2)使用constructor声明构造函数

    构造函数这个家伙要讲一讲,之前学java的时候是这样的

      a.构造函数要和类同名,     -> constructor已经足够

      b.构造函数个数不限定,     -> 我试了下,说是为了准确不允许多个

      c.构造函数中的参数不限定,

      d.当类被实例化时,先执行构造函数,

      e.类内没有自定义构造函数的,系统会给一个默认的空的构造函数,

      f.构造函数没有返回值,

    综上,我试了下,除上面的a、b不支持外,其余应该都是支持的

    (3)用this引用类成员

    (4)用new构造类的实例(也可以叫对象)

    (5)上面提到过new生成实例时会自动调用构造函数,那么传的参数自然是给构造函数的

     1 class Students{
     2 
     3     name : string;
     4     // 在构造函数里面添加一个参数
     5     constructor(message:string,age:number){
     6         this.name = message;
     7     };
     8 
     9     sayHi(){
    10         return "Hi "+this.name;
    11     };
    12 
    13 }
    14 
    15 var getStu = new Students("weizeyang");
    16 // error :supplied parameters do not match any signature of call target

    这个时候会报错,告诉我们说参数匹配不上

    3.继承

     举个栗子

     1 // 父类
     2 class College{
     3     department : string;
     4     constructor(name:string){
     5         this.department = name;
     6     };
     7     ceremony(num:number = 1){
     8         console.log(`本次典礼${this.department}共有${num}人参加`);
     9     }
    10 }
    11 
    12 // 继承1
    13 class Mathematical extends College{
    14     constructor(name:string,num:number){ 
    15         super(name); 
    16         this.ceremony(num);
    17     };
    18     own(owntype:string,ownnum:number){
    19         console.log(`${this.department}自己举办了一场${ownnum}人的典礼`);
    20     }
    21 }
    22 
    23 // 继承2
    24 class Exploration extends College{
    25     constructor(name:string){ 
    26         super(name); 
    27     };
    28     // 重写了父类的方法
    29     ceremony(num = 2){
    30         console.log("<--------不要脸的分割线------>");
    31         super.ceremony(num);    
    32     }
    33 }
    34 
    35 let college1 = new Mathematical("数理学院",3);
    36 // 本次典礼数理学院共有3人参加
    37 college1.own("数理",5);
    38 // 数理学院自己举办了一场5人的典礼
    39 
    40 let college2 = new Exploration("勘查技术学院");
    41 college2.ceremony(4);
    42 // <--------不要脸的分割线------>
    43 // 本次典礼勘查技术学院共有4人参加
    44 
    45 let college3 = new Exploration("勘查技术学院");
    46 college2.ceremony();
    47 // <--------不要脸的分割线------>
    48 // 本次典礼勘查技术学院共有2人参加

    这段代码有点长啊!但是,慢慢看来其实也并不长~

    (1)使用关键字extends继承父类。

    (2)子类可以访问父类的属性或方法。

    (3)包含constructor函数的派生类必须调用super(),它会执行父类的构造函数。

    (4)继承2中创建了ceremony方法,重写(覆盖)了从College继承来的ceremony方法,使得ceremony方法根据不同的类而具有不同的功能。

    (5)重写的概念:也叫覆盖,指在子类中定义一个和父类方法返回值、方法名、参数列表完全一致的方法。

    (6)super应用的两种语法:

        1)constructor内的super():执行父类的构造函数。必须至少执行一次。

        2)一般方法内的super.method():执行父类的(未必同名的)方法。不是必须的。

    (7)继承1中创建了除继承外的自己的own方法,并在里面使用了从父类继承了的department属性。

    4.常用的修饰符

    (1)public

    * 公有,public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用

    * 在typescript中,每个成员默认为public的,即可以自由的访问程序里面定义的成员。

    1 class College{
    2     public department : string;
    3     public constructor(name:string){
    4         this.department = name;
    5     };
    6     public ceremony(num:number = 1){
    7         console.log(`本次典礼${this.department}共有${num}人参加`);
    8     }
    9 }

    是和上面所举的例子是一样的

    (2)private(私有)

    * 私有,就是除了类自己之外,任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。 

    * 当成员被标记成private时,它就不能在声明它的类的外部访问(包括继承它的子类中)。

     1 class College{
     2     private department : string;
     3     constructor(name:string){
     4         this.department = name;
     5     };
     6     ceremony(num:number = 1){
     7         console.log(`本次典礼${this.department}共有${num}人参加`);
     8     }
     9 }
    10 
    11 class Mathematical extends College{
    12     constructor(name:string,num:number){ 
    13         super(name); 
    14         this.ceremony(num);
    15     };
    16     own(owntype:string,ownnum:number){
    17         console.log(`${this.department}自己举办了一场${ownnum}人的典礼`);   // error
    18     }
    19 }
    20 
    21 new College("数理").department;   // error

    上面的栗子17和21行报错 property 'departement' is private and only accessible within class 'College' ,意思是私有的departement这个变量只能在College这个类里面使用。

    * 共享了私有变量的派生类实例和该类的实例可以进行相互赋值,但是同为含有私有变量的类的实例不可以与该类进行赋值。

     1 class College{
     2     private department : string;
     3     constructor(name:string){
     4         this.department = name;
     5     };
     6 }
     7 
     8 class Mathematical extends College{
     9     constructor(name:string){ 
    10         super(name); 
    11     };
    12 }
    13 
    14 class Exploration{
    15     private department : string;
    16     constructor(name:string){
    17         this.department = name;
    18     };
    19 }
    20 
    21 var college1 = new College("1");
    22 var college2 = new Mathematical("1");
    23 var college3 = new Exploration("1");
    24 
    25 college1 = college2;
    26 college1 = college3;    // error
    27 college2 = college3;    // error
    
    

    这是26行报的错,27行同

    type 'Ecploration' is not assignable to type 'Mathematical' .

    types have separate declarations of a private property 'departemt'.

    意思是Ecploration不能给Mathematical赋值,因为departemt是私有的

    (3)protected

    * 受保护的,protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。

    * protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。

     1 class College{
     2     protected department : string;
     3     constructor(name:string){
     4         this.department = name;
     5     };
     6     ceremony(num:number = 1){
     7         console.log(`本次典礼${this.department}共有${num}人参加`);
     8     }
     9 }
    10 
    11 class Mathematical extends College{
    12     constructor(name:string,num:number){ 
    13         super(name); 
    14         this.ceremony(num);
    15     };
    16     own(owntype:string,ownnum:number){
    17         console.log(`${this.department}自己举办了一场${ownnum}人的典礼`);
    18     }
    19 }
    20 
    21 new College("数理").department;   // error

    参照上面(2)私有的第一个栗子。

    (4)参数属性

     依旧拿上面的例子搞事情

     1 class College{
     2   constructor(private name:string){};
     3   ceremony(num:number = 1){
     4     console.log(`本次典礼${this.name}共有${num}人参加`);
     5   }
     6 }
     7 
     8 let college = new College("数理");
     9 college.ceremony();
    10 
    11 // 本次典礼数理共有1人参加

    这样就减少了类中属性department的定义,在构造函数的使用了private name:string参数来创建和初始化name成员。我们把声明和赋值放在了一起。

    参数属性通过给构造函数参数添加一个访问限定符来声明。使用private限定一个参数属性会声明并初始化一个私有成员。

    对于public和protected也是一样的,但是要注意的是上面讲过成员默认的就是public的,但是在这里要显示的出现public才有效。

    5.存取器

    * 使用getter和setter可以改变属性的赋值和读取行为。

    下面的这个例子是从http://www.cnblogs.com/tansm/p/TypeScript_Handbook_Classes.html这里copy过来的....

    下面这个例子里,我们先检查用户密码是否正确,然后再允许其修改employee。 我们把对fullName的直接访问改成了可以检查密码的set方法。 我们也加了一个get方法,让上面的例子仍然可以工作。

     1 var passcode = "secret passcode";
     2 
     3 class Employee {
     4     private _fullName: string;
     5 
     6     get fullName(): string {
     7         return this._fullName;
     8     }
     9 
    10     set fullName(newName: string) {
    11         if (passcode && passcode == "secret passcode") {
    12             this._fullName = newName;
    13         }
    14         else {
    15             console.log("Error: Unauthorized update of employee!");
    16         }
    17     }
    18 }
    19 
    20 var employee = new Employee();
    21 employee.fullName = "Bob Smith";
    22 if (employee.fullName) {
    23     alert(employee.fullName);
    24 }

    我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改employee。

    注意:若要使用存取器,要求设置编译器输出目标为ECMAScript 5或更高。

    对,我的就是因为这个报错了....   error :  Accessors are only available when targeting ECMAScript 5 and higher.

    6.静态属性

    下面换个口味,用一个求环面柱体的体积的例子了解下静态属性和静态方法的使用

     1 class Volume{
     2     // 定义了一个静态属性
     3     static heigth = 10;
     4 
     5     // 声明并定义了一个静态函数
     6     static calculateVolume(secondRadius:number) {
     7 
     8       // 使用类的实例化成员smallRadius
     9       let smallRadius = new Volume(8).smallRadius;
    10       let area;
    11       if(secondRadius> smallRadius){
    12         area = Math.PI*(secondRadius*secondRadius - smallRadius*smallRadius);
    13       }
    14 
    15       // 使用类的静态属性
    16       return area*Volume.heigth;
    17     }
    18 
    19     constructor (private smallRadius: number) {
    20       if(smallRadius>5){
    21         smallRadius = 5;
    22       }
    23     }
    24 }
    25 
    26 // 调用了类的静态方法
    27 console.log(Volume.calculateVolume(9));

    (1) 用static修饰符修饰的方法或属性称为静态方法或静态属性

    (2)静态方法或属性不需要实例化,而是用 类.静态属性 的方式调用

    (3)在静态方法里面访问类的实例成员->9行

    再贴一个在网上看见的例子

     1 class Person{
     2   private static _instance:Person;
     3 
     4   static getInstance():Person{
     5     if(this._instance == null){
     6         this._instance = new Person();
     7     }
     8     return this._instance;
     9   }
    10 
    11   talk(){
    12     alert("Hi, my name is wzy!");
    13   }
    14 }
    15 
    16 function run(){
    17   Person.getInstance().talk();
    18 }
    19 
    20 run();   // 这里执行了12行的alert

    7.抽象类

    我照着上面在网上贴的例子改了下

    其中发现了一些问题

     1 abstract class Person{
     2   _instance:Person;
     3   constructor(public name:string){}
     4   abstract public getInstance():string;
     5 
     6   private talk(){                 
     7     return `my name is ${this.name}`;
     8   }
     9 }
    10 
    11 class Student extends Person{
    12   constructor(name:string){
    13     super(name);
    14   }
    15   getInstance(){
    16     this._instance = new Person("wzy");     // error : Person是抽象类,不能被实例化
    17     this._instance.talk();                  // error : 这里有三个错误     
    18   }                                         // (1)Person不能被实例化,所以不能调用它里面的方法
    19 }                                           // (2)即使被实例化了也不能调用这个方法,因为talk这个方法是私有的,不能在Person类外面使用
    20                                             // (3)getInstance这个方法实现的有错误,没有string返回值
    21
    var stu = new Student("weizeyang");
    22 console.log(stu.getInstance());

    改正了一下,有了下面的这个例子

     1 class Good{
     2   constructor(public name:string){}
     3   talk(){
     4     return `${this.name} is good student`;
     5   }
     6 }
     7 
     8 // 抽象类
     9 abstract class Person{
    10   // Good类型的属性
    11   _instance:Good;
    12   // 抽象类中的抽象方法
    13   abstract getInstance():string;
    14 }
    15 
    16 // 继承了抽象类
    17 class Student extends Person{
    18   // 实现了基类中的抽象方法
    19   getInstance(){
    20     this._instance = new Good("wzy");
    21     return this._instance.talk();
    22   }
    23 }
    24 
    25 var stu = new Student();
    26 console.log(stu.getInstance());

    (1)使用abstract定义抽象类和其中的抽象方法

    (2)抽象类不允许被实例化

    (3)抽象类中的抽象方法必须被子类实现

    (4)抽象方法的语法和接口方法相似,两者都是只声明不定义,即不包含方法体

    8.类的类型

     1 class Students{
     2    name : string;
     3    constructor(message:string){
     4        this.name = message;
     5    };
     6    sayHi(){
     7        return "Hi "+this.name;
     8    };
     9 }
    10 
    11 // 给了getStu一个Students这个类的类型
    12 var getStu:Students;
    13 getStu = new Students("weizeyang");

    类的这一篇终于要结束了,为了首尾呼应,最后用了本篇最开始的栗子 

    <----------------------------------------☺mizhiweixiao☺---------------------------------------->

    类的这一篇写的,真是把我的老血都熬出来了

  • 相关阅读:
    supervisor集群管理
    ansible安装es集群
    ansible安装应用实例
    ansible任务控制
    ansible的playbook基础
    ansiblie命令基础
    iptables命令详解
    ansible基础理论
    shell动态修改yml配置文件
    JAVA8 Stream()遍历求某列总和
  • 原文地址:https://www.cnblogs.com/wzy1569178479/p/7419298.html
Copyright © 2011-2022 走看看