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

 

類的這一篇寫的,真是把個人老血都熬出來了

相關文章
相關標籤/搜索