实例成员的访问修饰符
1、public 开放的/公开的。
当创建一个类时,成员默认的修饰符为public
class Person{
public name: string;
public constructor(name: string) {
this.name= name;
}
public Speak() :string {
alert("Hello, " + this.name);
}
}
let ps= new Person("world");
ps.Speak() // 通过实例化后的对象调用类里的方法
就拿上一篇文章中定义的类举例,所有属性和方法之前,如果不加其他的访问修饰符,成员默认的修饰符都为public。
2、private 私有的。
只能在类的内部访问 private修饰的成员,当前类的实例也不能访问,且不能被继承,继承后的对象实例化后也不能访问。constructor 也可以被 private访问修饰符修饰。
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // 错误: 'name' 是私有的.
当被protected访问修饰符修饰的成员,相当于给成员穿了一层防护。类的实例不能访问,不能被继承。
3、protected 受保护的。
与private不同的是,父类constructor中如果有属性,继承后的constructor中就得有super(),protected成员在派生类中依然可以访问(注:只能在子类 中 获取父类的受保护的属性方法)。被继承后的实例也不能访问。
super():执行父类的构造函数。
class Animal {
protected name: string
constructor(theName: string) {
this.name = theName;
}
run(distance: number) {
// this.name='xiaohuang'
console.log(`${this.name} moved ${distance}`)
console.log(this.name)
}
}
class Dog extends Animal{
constructor(name: string) {
super(name)
}
}
let animals = new Animal('xg')
let dog = new Dog('xxx')
dog.name // 访问不到
当属性name被访问修饰符protected修饰后,只能在类的内部访问 name属性,可以被继承,只能在派生类中能访问,继承后的实例也不能够访问。
4、readonly 只读的。
不能被修改。可以被继承 但是继承后的实例还是不能修改只读成员。
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
存取器
TypeScript支持通过get/set来截取对 对象成员 的访问。 它能帮助你有效的控制对对象成员的访问。
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
我们可以随意的设置 fullName,这是非常方便的,但是这也可能会带来麻烦。
我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改员工。
静态属性(static)
概念:不需要被实例化 访问的成员 称之为 静态成员,即只能被当前类访问的成员
和访问修饰符成员相似,static修饰的成员属性或是方法 ,只能通过类名. 成员名称 访问。不能够通过 实例对象 访问静态成员 。
class Grid {
static origin = {x: 0, y: 0};
calculateDistanceFromOrigin(point: {x: number; y: number;}) {
let xDist = (point.x - Grid.origin.x);
let yDist = (point.y - Grid.origin.y);
return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
}
constructor (public scale: number) { }
}
let grid1 = new Grid(1.0); // 1x scale
let grid2 = new Grid(5.0); // 5x scale
console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
抽象类(abstract)
抽象类 使用abstract 修饰,抽象类可以有普通的方法,也可以有抽象的方法,但是抽象的方法不能被实现,只能在派生类中实现(普通类中不能有抽象的方法),抽象类不能够被实例化。
不同于接口,抽象类可以包含成员的实现细节
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
接口与抽象类的区别:
相同点:
1、都不能被实例化。
2、接口的实现类和抽象类的子类只有全部实现了接口或者抽象类中的方法后才可以被实例化。
不同点:
1、接口只能定义抽象方法不能实现方法,抽象类既可以定义抽象方法,也可以实现方法。
2、单继承,多实现。接口可以实现多个,只能继承一个抽象类。
3、接口强调的是功能,抽象类强调的是所属关系。
4、接口中的所有成员变量 为public static final, 静态不可修改,当然必须初始化。接口中的所有方法都是public abstract 公开抽象的。而且不能有构造方法。抽象类就比较自由了,和普通的类差不多,可以有抽象方法也可以没有,可以有正常的方法,也可以没有。
抽象类强调的是从属关系,接口强调的是功能。
方法重载
方法名相同,参数类型或个数不同,返回类型可以相同也可以不同。
(可以根据所传递进来的不同参数,决定具体调用哪个函数。)
相同点:
1、都不能被实例化。
2、接口的实现类和抽象类的子类只有全部实现了接口或者抽象类中的方法后才可以被实例化。
不同点:
1、接口只能定义抽象方法不能实现方法,抽象类既可以定义抽象方法,也可以实现方法。
2、单继承,多实现。接口可以实现多个,只能继承一个抽象类。
3、接口强调的是功能,抽象类强调的是所属关系。
4、接口中的所有成员变量 为public static final, 静态不可修改,当然必须初始化。接口中的所有方法都是public abstract 公开抽象的。而且不能有构造方法。抽象类就比较自由了,和普通的类差不多,可以有抽象方法也可以没有,可以有正常的方法,也可以没有。
抽象类强调的是从属关系,接口强调的是功能。
方法重载与方法重写的区别:
方法的重写(Overrriding):当一个类继承另外一个类的时候,那么该类(子类/派生类)就拥有了其父类(基类)的成员方法和成员变量。在子类当中,可以创建属于自己独有的成员,如果创建了一个与父类中名称相同、参数列表相同的方法,只是方法体中的实现形式不相同,以实现与父类的功能不相同,这种方式就被称为方法的重写,也被称为方法的覆盖。
()
方法的重载(Overloading):方法的重载是指在一个类当中,有多个方法,而且这些方法的名字是相同的,但是参数列表和返回值是不相同,当重载的时候,方法名的名称是被共享的,但是参数类型和参数个数是不相同的,返回值类型可以相同也可以不相同。