TypeScript入门四:TypeScript的类(class)
<ul style="color: rgba(41, 78, 128, 1)"><li>TypeScript类的基本使用(修饰符)</li>
<li>TypeScript类的抽象类(abstract)</li>
<li>TypeScript类的高级技巧</li>
</ul>
<h2 style="background-color: rgba(41, 78, 128, 1); border-radius: 5px"> 一、TypeScript类的基本使用(修饰符)</h2>
<p>TypeScript的类与ES6的类非常类是,所以建议先了解ES6的类的相关内容:ES6入门六:class的基本语法、继承、私有与静态属性、修饰器。</p>
<p>1.最简单的TypeScript的类示例与ES6实现对比:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">class tsClass{
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> public a:string ; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">公有成员</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span> private b:number[] ; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">私有成员</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> protected c:string[] ; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">被保护的成员</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> static e:string = 'e'; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">静态属性</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">constructor(astr:string,barr:number[],carr:string[]){
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.a =<span style="color: rgba(0, 0, 0, 1)"> astr;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.b =<span style="color: rgba(0, 0, 0, 1)"> barr;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.c =<span style="color: rgba(0, 0, 0, 1)"> carr;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">class SublevelCla extends tsClass {
</span><span style="color: rgba(0, 128, 128, 1)">13</span> private dname: string; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">私有成员</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">constructor (astr:string,barr:number[],carr:string[],dname:string){
</span><span style="color: rgba(0, 128, 128, 1)">15</span> super(astr,barr,carr);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">继承tsClass构造字段</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.dname = dname;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">sublevelCla自身构造字段</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">18</span> fun():<span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">19</span> console.log(tsClass.e);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通过类获取静态成员</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">22</span>
<span style="color: rgba(0, 128, 128, 1)">23</span> let sub = <span style="color: rgba(0, 0, 255, 1)">new</span> SublevelCla('a',,['a','b','c'],'sublevelName'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)">sub.fun();
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 0, 1)">console.log(sub.a);
</span><span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(sub.b); //报错:私有成员不能被外部访问</span>
<span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(sub.c); //报错:被保护的成员不能被外部访问</span>
<span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(sub.dname); //报错:私有成员不能被外部访问</span></pre>
</div>
<p>Ts类与Js类的修饰符对比:</p>
<p>Ts有公共成员(public)修饰符;Js没有该修饰符,但可以在构造函数constructor内直接使用this定义公共成员,用于生成每个实例对象的属性。</p>
<p>Ts有私有成员(private)修饰符;Js的私有成员修饰符是(#),该成员只能在当前类中使用,TS与JS没有区别。</p>
<p>Ts有受保护成员(protected)修饰符;Js没有该修饰符,也没有对应的成员语法。在Ts中受保护成员可以被字类访问在子类中使用,但不能被实例对象在外部访问。</p>
<p>Ts有静态成员(static)修饰符;Js中也有同样的修饰符,该成员最终被解析到类的自身属性上(解析成ES5的话就是函数的属性),静态属性可以被类名直接在任何地方引用。</p>
<p>Ts有只读成员(readonly)修饰符;Js中没有该修饰符,但是可以通过属性访问器get来实现。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">js示例代码</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">class jsClass{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> #b ;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)"> #c ;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> static e = 'e'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)"> constructor(astr,barr,carr,){
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.a =<span style="color: rgba(0, 0, 0, 1)"> astr;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.#b =<span style="color: rgba(0, 0, 0, 1)"> barr;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.#c =<span style="color: rgba(0, 0, 0, 1)"> carr;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">12</span>
<span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 0, 1)">class jsSubc extends jsClass{
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)"> constructor(astr,barr,carr,dname){
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)"> super(astr,barr,carr);
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.dname =<span style="color: rgba(0, 0, 0, 1)"> dname;
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)"> fun(){
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)"> console.log(jsClass.e);
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">22</span> let jsub = <span style="color: rgba(0, 0, 255, 1)">new</span> jsSubc('a',,['a','b','c'],'sublevelName'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)">jsub.fun();
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)">console.log(jsub.a);
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(jsub.b);//undefined</span></pre>
</div>
<p>关于类的继承在Ts和Js中都是使用extends关键字,并且在构造函数中使用super方法实现构造继承,这个方法都必须写在字类构造函数内的最前面。</p>
<p>Ts受保护的成员的使用方式就是通过添加到父类构造函数,然后字类构造继承该成员,在子类中就能使用this关键字访问该成员了,子类中不需要再在自生声明该成员了。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个官方示例完美的展示了受保护成员的应用</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">class Person {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> protected name: string;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> constructor(name: string) { <span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; }
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)">class Employee extends Person {
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> private department: string;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)"> constructor(name: string, department: string) {
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)"> super(name)
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.department =<span style="color: rgba(0, 0, 0, 1)"> department;
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">14</span>
<span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)"> public getElevatorPitch() {
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">return</span> `Hello, my name is ${<span style="color: rgba(0, 0, 255, 1)">this</span>.name} and I work <span style="color: rgba(0, 0, 255, 1)">in</span> ${<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.department}.`;
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">19</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> let howard = <span style="color: rgba(0, 0, 255, 1)">new</span> Employee("Howard", "Sales"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">console.log(howard.getElevatorPitch());
</span><span style="color: rgba(0, 128, 128, 1)">22</span> console.log(howard.name); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 错误</span></pre>
</div>
<p> Ts只读成员示例在官方文档中也有非常好的示例,这里直接复制展示该示例:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">class Octopus {
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 0, 1)"> readonly name: string;
</span><span style="color: rgba(0, 128, 128, 1)">3</span> readonly numberOfLegs: number = 8<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 0, 1)"> constructor (theName: string) {
</span><span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> theName;
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">7</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">8</span> let dad = <span style="color: rgba(0, 0, 255, 1)">new</span> Octopus("Man with the 8 strong legs"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">9</span> dad.name = "Man with the 3-piece suit"; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 错误! name 是只读的.</span></pre>
</div>
<p>同样Ts中也可以使用set与get作为存取器,通过属性访问器setter和getter实现的成员相当于定义了一个(public)公有成员,每个实例都会产生自己的实例属性,唯一的区别就是在不写入值时会读取类中定义的私有属性值,这个特性与JS完全一致。常见的使用访问器实现读写私有属性(一般只写):</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">class Person{
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> private _name: string = 'person'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给私有属性赋值</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)">set setName(val:string){
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">this</span>._name =<span style="color: rgba(0, 0, 0, 1)"> val;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取私有属性值(一般不建议使用)</span>
<span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">get getName(){
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._name;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">var</span> obj1 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">var</span> obj2 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
</span><span style="color: rgba(0, 128, 128, 1)">14</span> obj1.setName = 'obj1'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">15</span> console.log(obj2.getName);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">person</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> console.log(obj1.getName);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">obj1</span></pre>
</div>
<div class="cnblogs_code"><img id="code_img_closed_03848e3a-ab60-49b1-bc9b-8b3909813217" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_03848e3a-ab60-49b1-bc9b-8b3909813217" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_03848e3a-ab60-49b1-bc9b-8b3909813217" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">js</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">class Person{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> #name = 'person'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给私有属性赋值</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)"> set setName(val){
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.#name =<span style="color: rgba(0, 0, 0, 1)"> val;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取私有属性值(一般不建议使用)</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)"> get getName(){
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.#name;
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">var</span> obj1 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">var</span> obj2 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
</span><span style="color: rgba(0, 128, 128, 1)">15</span> obj1.setName = 'obj1'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">16</span> console.log(obj2.getName);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">person</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> console.log(obj1.getName);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">obj1</span></pre>
</div>
<span class="cnblogs_code_collapse">js示例</span></div>
<h2 style="background-color: rgba(41, 78, 128, 1); border-radius: 5px"> 二、TypeScript类的抽象类(abstract)</h2>
<p>关于抽象类需要先理解几个概念,什么是抽象类,什么是派生类,什么是抽象类型的引用。</p>
<p>抽象类顾名思义就是类的抽象,它不是用来具体实现对象实例化的类,而是定义类结构。比如规定类必须要实现那些方法和成员变量,但其自身并不做具体细节实现,这些方法也叫做抽象方法和抽象成员变量(同样使用abstract关键字修饰),这些被抽象出来的方法和成员变量必须在派生类中实现。抽象类自身也可以包含成员的实现细节,比如定义构造函数的具体内容,成员变量和方法,这些实现细节会被派生类继承用于实例化具体的对象。</p>
<p>派生类就是抽象类的具体实现,在派生类中必须实现抽象类中定义的抽象方法和成员变量,并且不能随意增加抽象类没有定义的方法和成员变量(即使能在抽象类中实现,但是不能被抽象类的引用使用这些在派生类中私自定义的内容,但可以被非抽象类引用的变量接收),这一点与继承是有区别的。并且在构造函数constructor内必须使用super()方法继承抽象类的构造。</p>
<p>抽象类型的引用就是变量类型为抽象类的变量,该变量只能引用抽象类对应的派生类构造的对象,并且只能使用抽象类自身实现的细节内容和抽象内容,而不能使用派生类中实现的非抽象内容。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">abstract class Department {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">constructor(public name: string) {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> printName(): <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> console.log('Department name: ' + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.name);
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> abstract printMeeting(): <span style="color: rgba(0, 0, 255, 1)">void</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 必须在派生类中实现</span>
<span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">class AccountingDepartment extends Department {
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">public a:string;
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">constructor() {
</span><span style="color: rgba(0, 128, 128, 1)">13</span> super('Accounting and Auditing'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在派生类的构造函数中必须调用 super()</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.a='aaa'
<span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">16</span> printMeeting(): <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">17</span> console.log('The Accounting Department meets each Monday at 10am.'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">19</span> generateReports(): <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">20</span> console.log('Generating accounting reports...'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">23</span>
<span style="color: rgba(0, 128, 128, 1)">24</span>
<span style="color: rgba(0, 128, 128, 1)">25</span>
<span style="color: rgba(0, 128, 128, 1)">26</span> let department: Department; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 允许创建一个对抽象类型的引用</span>
<span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> department = new Department(); // 错误: 不能创建一个抽象类的实例</span>
<span style="color: rgba(0, 128, 128, 1)">28</span> department = <span style="color: rgba(0, 0, 255, 1)">new</span> AccountingDepartment(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 允许对一个抽象子类进行实例化和赋值</span>
<span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)">department.printName();
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 0, 1)">department.printMeeting();
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> department.generateReports(); // 错误: 方法在声明的抽象类中不存在</span>
<span style="color: rgba(0, 128, 128, 1)">32</span>
<span style="color: rgba(0, 128, 128, 1)">33</span> let accounting = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AccountingDepartment();<span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">非抽象引用变量能接收的派生类实例对象</span></span>
</span><span style="color: rgba(0, 128, 128, 1)">34</span> accounting.generateReports();<span style="color: rgba(0, 128, 0, 1)">//并且</span><span style="color: rgba(0, 128, 0, 1)">能使用派生类自身定义的内容</span></pre>
</div>
<h2 style="background-color: rgba(41, 78, 128, 1); border-radius: 5px"> 三、TypeScript类的高级技巧</h2>
<p> 1.构造函数</p>
<p>关于构造函数作为类的核心内容,是每个类实例化对象时new指令直接调用的方法,实际上TypeScript与ES6在这方面并没有差别,如果了解ES6的化我们都知道class只是一个语法糖,它的底层实现还是function,类中的构造函数就是ES5的方法主体,它最终被赋给该方法原型上的constructor属性,而类中实现的一系列的修饰符和特性最后都会被解析为类自身或者原型上的属性和方法,用来配合主体方法实现对象实例的构造。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ES5基于function实现的类</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> let Greeter = (<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Greeter(message) {
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.greeting =<span style="color: rgba(0, 0, 0, 1)"> message;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> Greeter.prototype.greet = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">return</span> "Hello, " + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.greeting;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Greeter;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">})();
</span><span style="color: rgba(0, 128, 128, 1)">11</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">let greeter;
</span><span style="color: rgba(0, 128, 128, 1)">13</span> greeter = <span style="color: rgba(0, 0, 255, 1)">new</span> Greeter("world"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">14</span> console.log(greeter.greet());</pre>
</div>
<p>再来对比看一下TypeScript的改写实现:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">class Greeter {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> static standardGreeting = "Hello, there"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> greeting: string;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)"> greet() {
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.greeting) {
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">return</span> "Hello, " + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.greeting;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Greeter.standardGreeting;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">13</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">let greeter1: Greeter;
</span><span style="color: rgba(0, 128, 128, 1)">15</span> greeter1 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Greeter();
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)">console.log(greeter1.greet());
</span><span style="color: rgba(0, 128, 128, 1)">17</span>
<span style="color: rgba(0, 128, 128, 1)">18</span> let greeterMaker: <span style="color: rgba(0, 0, 255, 1)">typeof</span> Greeter =<span style="color: rgba(0, 0, 0, 1)"> Greeter;
</span><span style="color: rgba(0, 128, 128, 1)">19</span> greeterMaker.standardGreeting = "Hey there!"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">20</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> let greeter2: Greeter = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> greeterMaker();
</span><span style="color: rgba(0, 128, 128, 1)">22</span> console.log(greeter2.greet());</pre>
</div>
<p>2.把类当成接口(关于接口在TypeScript接口相关博客中会有更详细的内容)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">class Point {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)"> x: number;
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> y: number;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">interface Point3d extends Point {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> z: number;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> let point3d: Point3d = {x: 1, y: 2, z: 3};</pre>
</div>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
——生命自会找到蓬勃之路。<br><br>
来源:https://www.cnblogs.com/ZheOneAndOnly/p/11780535.html
頁:
[1]