原文链接: typescript 类和接口
上一篇: win10 串口 使用
简单类
class Stu {
name: string;
constructor(name: string) {
this.name = name;
}
say(): string {
return `hello ${this.name}`
}
}
let stu = new Stu("ace")
// hello ace
console.log(stu.say());
与强类型语言类似,TypeScript的类成员可以显式声明访问级别:public、protected、private
在TypeScript里,如果不显示指定访问级别,则默认为public。
class User {
name: string;
private sex: string;
protected age: number;
constructor(_name: string) {
this.name = _name;
}
sayHello(): string {
return `Hello,${this.name}!`;
}
}
let user = new User('John Reese');
user.name = 'Root'; // 公有属性,可以赋值
user.sex = 'female'; // 私有属性,无法赋值
user.age = 28; // 受保护属性,无法赋值
user.sayHello();
属性的get和set访问器
通过get和set关键字声明属性访问器,通过属性访问器可以精确控制属性的赋值和获取值。
class User {
private _name: string;
get name(): string {
return this._name;
}
set name(newName: string) {
this._name = newName;
}
constructor(_name: string) {
this.name = _name;
}
sayHello(): string {
return `Hello,${this._name}!`;
}
}
let user = new User('John Reese');
user.name = 'Root';
user.sayHello();
静态属性
静态属性即是通过类型而不是实例就可以访问的属性
通过static关键字可以声明类型的静态属性。
class User {
static sex_type = ['male', 'female']; // 静态属性
name: string;
sex: string;
constructor(_name: string) {
this.name = _name;
}
sayHello(): string {
return `Hello,${this.name}!`;
}
}
let user = new User('John Reese');
user.name = 'Root';
user.sex = User.sex_type[1];
user.sayHello();
类的继承
同强类型语言一样,TypeScript也支持类的继承
子类通过extends关键字可以继承其他类,通过super方法调用基类对应的方法,也可以直接重写基类的方法。
// 基类
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 吃食物。`);
}
}
// 子类继承基类
class Dog extends Animal {
constructor(theName: string) {
super(theName);
}
eat() {
super.eat();
console.log('并且吃的是狗粮。');
}
}
class People extends Animal {
constructor(theName: string) {
super(theName);
}
// 子类重写基类方法
eat() {
console.log(`${this.name} 拒绝吃狗粮。`);
}
}
let animal = new Animal('动物');
animal.eat();
let dog: Animal;
dog = new Dog('狗');
dog.eat();
let people: Animal;
people = new People('人类');
people.eat();
抽象类
通过abstract关键字声明抽象类和抽象方法,子类继承抽象类后,需要实现抽象方法。同样的,抽象类不能被实例化。
// 抽象类
abstract class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
abstract eat();
}
// 子类继承抽象类
class Dog extends Animal {
constructor(theName: string) {
super(theName);
}
eat() {
console.log(`${this.name} 吃狗粮。`);
}
}
let animal = new Animal('动物'); // 抽象类无法实例化
animal.eat();
let dog: Animal;
dog = new Dog('狗');
dog.eat();
接口
在JavaScript里没有对应的类型与之对应,所以编译之后不会生成任何JavaScript代码。
简单接口
interface Animal {
name: string;
}
1. 作为参数类型
接口类型可以作为方法的参数类型,效果等同于直接指定Json对象的类型。
interface Animal {
name: string;
}
let printName = function(param: Animal) {
console.log(`Name is ${param.name}`);
}
printName({name: 'Dog'});
接口成员也可以是缺省的
interface Animal {
name: string;
age?: number;
}
let printName = function (param: Animal) {
if (param.age) {
console.log(`Name is ${param.name}, and age is ${param.age}`);
} else {
console.log(`Name is ${param.name}`);
}
}
printName({ name: 'Dog' });
printName({ name: 'Dog', age: 5 });
但是在某些情况下,调用方法时,参数赋值可能会有多个,接口在作为参数类型时也支持拥有多个成员的情况。
interface Animal {
name: string;
age?: number;
[propName: string]: any; // 其他成员
}
let printName = function (param: Animal) {
if (param.age) {
console.log(`Name is ${param.name}, and age is ${param.age}`);
} else {
console.log(`Name is ${param.name}`);
}
}
printName({ name: 'Dog' });
printName({ name: 'Dog', age: 5 });
printName({ name: 'Dog', age: 5, character: '粘人' }); // 多于明确定义的属性个数
作为其他类型
接口也可以定义方法的类型,和数组类型
interface FuncType {
(x: string, y: string): string; // 声明方法成员
}
let func1: FuncType;
func1 = function (prop1: string, prop2: string): string { // 方法参数名称不需要与接口成员的参数名称保持一致
return prop1 + ' ' + prop2;
}
interface ArrayType {
[index: number]: string; // 声明数组成员
}
let arr: ArrayType;
arr = ['Dog', 'Cat'];
接口的继承与实现
同强类型语言一样,TypeScript的接口支持继承与实现。
interface Animal {
name: string;
eat(): void;
}
class Dog implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 吃狗粮。`)
}
}
class Cat implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 吃猫粮。`)
}
}
let dog: Animal;
dog = new Dog('狗狗');
dog.eat();
let cat: Animal;
cat = new Cat('喵星人');
cat.eat();
类通过implements关键字继承接口,并实现接口成员。
同时,接口也可以多重继承。
interface Animal {
name: string;
eat(): void;
}
interface Person extends Animal { // 继承自Animal接口
use(): void;
}
class People implements Person {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 拒绝吃狗粮。`)
}
use() {
console.log(`${this.name} 会使用工具。`)
}
}
let man: Person;
man = new People('男人');
man.eat();
man.use();
类型转换
在TypeScript里,接口可以对符合任一成员类型的对象进行转换,转换之后的对象自动继承了接口的其他成员。
声明了拥有name属性的json对象,通过<>将json对象转换成了Animal类型的对象。转换后的对象则拥有了另外的age属性和eat方法。
interface Animal {
name: string;
age: number;
eat(): void;
}
let thing = { name: '桌子' };
let otherThing = <Animal>thing; // 类型转换
otherThing.age = 5;
otherThing.eat = function () {
console.log(`${this.name} 不知道吃什么。`)
};
接口继承类
在TypeScript里,接口可以继承类,这样接口就具有了类里的所有成员,同时这个接口只能引用这个类或者它的子类的实例。
当继承链过深,代码需要在某一个子类的类型下执行时,这种方法比较有效。
class People {
name: string;
private age: number;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 拒绝吃狗粮。`);
}
use() {
console.log(`${this.name} 会使用工具。`)
}
}
interface Animal extends People { // 接口
}
class Man extends People { // 子类
}
class Cat { // 拥有同样结构的另外一个类
name: string;
private age: number;
constructor(theName: string) {
this.name = theName;
}
eat() {
// 具体实现
}
use() {
// 具体实现
}
}
let cat: Animal;
cat = new Cat('喵星人'); // Cat类不是People的子类,无法被Animal引用
let man: Animal;
man = new Man('男人');
man.eat();