首先我们要清楚 privateprotected 现阶段只是javascript中的保留字(Reserved words),而非关键字(Keywords )。因此TypeScript中的纯类型声明语句,编译后都会被擦除。

class Person {
public name: string;
protected age: number;
private isMarried: boolean;
}
//编译结果
class Person {
}

TypeScript是一个结构类型语言。当比较两个不同的类型时,不管它们来自哪里,如果所有成员的类型都是兼容的,那么就说这些类型本身是兼容的。

interface Named {
name: string;
} class Bar {
name: string;
} class Foo {
name: string;
} // OK, because of structural typing
let a: Named = new Person(); //️
let b: Foo = new Bar(); //️

由于 TypeScript 属性声明默认是 public,所以上面可以以 b.name 形式访问,而java则默认是protected

但是,当比较具有 private 成员或 protected 成员的类型时,会区别对待这些类型。如果其中一种类型具有private成员,那么另一种类型必须具有来源于同一处声明的private成员。这同样适用于protected成员。

class Bar {
private name: string;
} class Foo {
private name: string;
} let bar: Bar = new Foo(); //
//Type 'Foo' is not assignable to type 'Bar'.
//Types have separate declarations of a private property 'name'.

上面的这些概念规则来源于 TypeScript Handbook,这里只是做个简要的引子。

TypeScript 在判断类型兼容时,为什么处理 privateprotected 的规则要有别于 public , 这究竟有什么潜在的好处。

假设有这样一个场景,目前电动汽车尚且处于发展的初级阶段,汽车品牌特斯拉、蔚来的最大里程数 maxMileage 值一样。

interface Car {
maxMileage: number;
} class Tesla implements Car {
maxMileage: number = 500;
} class Nio implements Car {
maxMileage: number = 500;
} function drive(car :Tesla) {
console.log(car.maxMileage)
} let tesla = new Tesla();
let nio = new Nio();
drive(tesla); // ️
drive(nio); // ️

由于TypeScript是结构式语言,因TeslaNio又有着相同名称、类型的字段 maxMileage ,即使 drive 入参声明为 Tesla 类型,也能通过校验。目前而言,即使误用,drive 的表现一样,不会有问题,但随着技术的发展,两个品牌的 maxMileage 值将不一样,drive 的行为也将千差万别。这个bug将一直潜伏着,直到引起严重故障才会引起关注。

在上例基础上增加1) 2) 两处,多了 private(protected亦可) 声明的 brand 属性,来解决结构一样,但又想区分类型的场景,达到类似声明式类型系统的效果。这里就是利用了privateprotected属性必须源于同一处声明才可判定类型兼容。

class Tesla implements Car {
private brand: string = "Tesla"; // 1)
maxMileage: number = 500;
} class Nio implements Car {
private brand: string = "Tesla"; //2)
maxMileage: number = 500;
} function drive(car :Tesla) {
console.log(car.maxMileage)
}
let tesla = new Tesla();
let nio = new Nio();
drive(tesla); // ️
drive(nio); //
//Argument of type 'Nio' is not assignable to parameter of type 'Tesla'.
//Types have separate declarations of a private property 'brand'. //编译后
class Tesla {
constructor() {
this.brand = "Tesla";
this.maxMileage = 500;
}
}
class Nio {
constructor() {
this.brand = "Tesla";
this.maxMileage = 500;
}
}

虽然达到了我们想要的效果,但类实例会多出 brand 属性,增加了运行时开销,如果这不是你想要的,可以如下处理:

class Tesla implements Car {
//@ts-ignore
private brand: string;
maxMileage: number = 500;
} class Nio implements Car {
//@ts-ignore
private brand: string ;
maxMileage: number = 500;
} //编译后
class Tesla {
constructor() {
this.maxMileage = 500;
}
}
class Nio {
constructor() {
this.maxMileage = 500;
}
}

可以看到编译后的代码很纯净了。//@ts-ignore仅在 strictPropertyInitialization: true 时需要,避免因未初始化属性而编译报错。

Types have separate declarations of a private property 报错还会出现在类extends继承的时候。初看很奇怪,使用姿势不同,但报错信息且类似。

class ElectricVehicle {
private charge() {};
} //Type 'FF91' is not assignable to type 'ElectricVehicle'.
// Types have separate declarations of a private property 'charge'
class FF91 extends ElectricVehicle { //
private charge() {};
}

通过将 private 改成 protected或public 可以修复。很多文章会提到这是由于 private 语义上是私有的,对子类不可见,所以不能进行覆盖,而protectedpublic 语义上就是对子类可见的,子类知道当前在进行覆盖行为,这只是一方面。

我们假设 TypeScript 允许覆盖 private 方法,上面的类声明编译通过。但当我们执行下面语句时,上面的报错再次出现。

let parent = new ElectricVehicle();
let child = new FF91();
parent = child; //
//Type 'FF91' is not assignable to type 'ElectricVehicle'.
// Types have separate declarations of a private property 'charge'

最初的示例,Foo、Bar 只是两个结构类似的类,并无继承关系,判定类型不兼容尚可理解。这里父子类之间类型不兼容就没法自圆了。

所以编译器提前在类声明时就报错,避免延后到使用阶段。这也是为什么 FF91 类声明继承时的报错信息和前面的一样。

示例 Playground

TypeScript中的private、protected的更多相关文章

  1. Java中public,private,protected,和默认的区别

    Java中public,private,protected,和默认的区别 1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以 ...

  2. php class中public,private,protected的区别,以及实例

    一,public,private,protected的区别 public:权限是最大的,可以内部调用,实例调用等. protected: 受保护类型,用于本类和继承类调用. private: 私有类型 ...

  3. PHP中public,private,protected,abstract等关键字用法详解

    PHP中常用的关键字 在PHP中包含了很多对函数和类进行限制的关键字,常用的通常有abstract,final,interface,public,protected,private,static等等, ...

  4. 解析Visual C# 7.2中的private protected访问修饰符

    去年12月份,随着Visual Studio 2017 Update 15.5的发布,Visual C#迎来了它的最新版本:7.2. 在这个版本中,有个让人难以理解的新特性,就是private pro ...

  5. java中public private protected default的区别

    1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直 ...

  6. Java中的private protected public和default的区别

    转至:http://blog.sina.com.cn/s/blog_74c571240101jaf5.html    类内部  本包  子类 外部包  public    √  √  √  √ pro ...

  7. php 中 public private protected的区别

    public 子类,外部都可调用. protected 子类可以调用,外部不可以调用. private 子类不可以调用,外部不可以调用. <?php class AA { public func ...

  8. C++中的private/protected/public

    访问权限: 继承关系:

  9. C++中public、protected及private用法

    转自:http://www.jb51.net/article/54224.htm 初学C++的朋友经常在类中看到public,protected,private以及它们在继承中表示的一些访问范围,很容 ...

随机推荐

  1. python之hashlib、suprocess模块

    一.hashlib模块 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 ...

  2. Windows下使用Graalvm将Javafx应用编译成exe

    1 背景 Graalvm是Oracle推出的一款新型虚拟机,其中一个吸引人的功能是:它可以将Java代码编译成各个平台的本地代码,这些平台包括:linux.macOS.windows.iOS.andr ...

  3. MySQL--运行机制,SQL执行顺序,Explain

    MySQL的运行机制是什么?  首先客户端先要发送用户信息去服务器端进行授权认证,当输入正确密码之后可以连接到数据库了,当连接服务器端成功之后就可以正常的执行 SQL 命令了,MySQL 服务器拿到 ...

  4. 第8章 控制对象的访问(setter、getter、proxy)

    目录 1. 使用getter和setter控制属性访问 1.1 定义getter与setter 通过对象字面量定义,或在ES6的class中定义 通过使用内置的Object.definePropert ...

  5. 发现一个怪象windows 7系统上老是丢包windows 10网络正常

    不知何故障,同一个局域网,windows 10系统上不丢包,windows 7系统老是丢包,不知是不是这二个系统的差区别,还是大家都有这样的情况. 相互PC之间ping也又不丢包,只有windos 7 ...

  6. 【SpringBoot1.x】SpringBoot1.x 分布式

    SpringBoot1.x 分布式 分布式应用 Zookeeper&Dubbo ZooKeeper 是用于分布式应用程序的高性能协调服务.它在一个简单的界面中公开了常见的服务,例如命名,配置管 ...

  7. 剑指offer 面试题10.2:青蛙变态跳台阶

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级--它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 编程思想 因为n级台阶,第一步有n种跳法:跳1级.跳2级.到跳n级跳1级,剩下 ...

  8. load data local带来的安全问题

    load data默认读的是服务器上的文件,但是加上local参数后,就可以将本地具有访问权限的文件加载到数据库中,这在带来方便的同时,也带来了以下安全问题, 可以任意加载本地文件到数据库, 在web ...

  9. AWS IoT Greengrass是什么?V1和V2版本及其差异

    AWS IoT Greengrass ​ Greengrass主要是用于边缘计算或者机器学习有关,对于详细了解请阅读结尾处的官方文档,文档内容也较为丰富. 目录 AWS IoT Greengrass ...

  10. 写给 Linux 初学者的一封信

    大家好,我是肖邦. 这篇文章是写给 Linux 初学者的,我会分享一些作为初学者应该知道的一些东西,这些内容都是本人从事 Linux 开发工作多年的心得体会,相信会对初学者有所帮助.如果你是 Linu ...