首先我们要清楚 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. 神经网络中的降维和升维方法 (tensorflow & pytorch)

    大名鼎鼎的UNet和我们经常看到的编解码器模型,他们的模型都是先将数据下采样,也称为特征提取,然后再将下采样后的特征恢复回原来的维度.这个特征提取的过程我们称为"下采样",这个恢复 ...

  2. Hive表的基本操作

    目录 1. 创建表 2. 拷贝表 3. 查看表结构 4. 删除表 5. 修改表 5.1 表重命名 5.2 增.修.删分区 5.3 修改列信息 5.4 增加列 5.5 删除列 5.6 修改表的属性 1. ...

  3. python+sklearn+kaggle机器学习

    python+sklearn+kaggle机器学习 系列教程 0.kaggle 1. 初级线性回归模型机器学习过程 a. 提取数据 b.数据预处理 c.训练模型 d.根据数据预测 e.验证 今天是10 ...

  4. Hadoop源码:namenode格式化和启动过程实现

    body { margin: 0 auto; font: 13px / 1 Helvetica, Arial, sans-serif; color: rgba(68, 68, 68, 1); padd ...

  5. SAP中用户口令状态的一点说明

    数据元素:XUPWDSTATE 数值      内涵 -2(通常)不能更改口令.-1(每天只允许一次)今天不能更改口令.0可以更改口令,但没有必要更改.1口令为初始值必须更改口令.2口令过期必须更改口 ...

  6. [Ceoi2004]Journey

    题目描述 给出N个点,及你的出发点K. 接下来N-1行描述有关边的开始点,结束点,边长.保证图中不会有环 接下来给出数字J,代表你要走多少个点. 接下来J个数字,代表你要走过的点的编号.当然你可以自己 ...

  7. canvas星空背景特效+CSS旋转相册学习

    今天在看帖子的时候,看到了个有趣的css旋转相册,刚好之前做了一个星空背景dome,这里给大家分享下代码: 旋转相册参考:https://blog.csdn.net/gitchatxiaomi/art ...

  8. 深圳某小公司面试题:AQS是什么?公平锁和非公平锁?ReentrantLock?

    AQS总体来说没有想象中那么难,只要了解它的实现框架,那理解起来就不是什么问题了. AQS在Java还是占很重要的地位的,面试也是经常会问. 目前已经连载11篇啦!进度是一周更新两篇,欢迎持续关注 [ ...

  9. LVS负载均衡理论以及算法概要

    一. LVS简介 LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.or ...

  10. SpringBoot 报错: Circular view path [readingList] 解决办法

    spring boot报错: Circular view path [readingList]: would dispatch back to the current handler URL [/re ...