13.typescript-类

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

 

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

 

1.类的相关概念typescript

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

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

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

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

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

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

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

(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☺---------------------------------------->

 

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

相关文章
相关标签/搜索