晚上睡不着 早上睡不着 中午睡不着 想睡覺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☺---------------------------------------->
類的這一篇寫的,真是把個人老血都熬出來了