TypeScript Essential Notes 5 - Classes

Understanding prototypical inheritance

function TodoService(){
  this.todos =[];
}

TodoService.prototype.getAll = function(){
  return this.todos;
}


var service = new TodoService();
service.getAll();

this 关键字指的是对象的实例。所以第六行的 this.todos 会在运行时引用第二行的 this.todos

JavaScript 为对象分配原型的最常见方式是使用构造函数,它实际上只是一个使用 new 关键字调用的函数。当您使用 new 关键字初始化对象时,JavaScript 会做三件事。首先,它创建一个新对象。其次,它将新对象的原型设置为构造函数的原型。第三,它执行您使用 new 关键字调用的函数,在该方法中将新对象称为 this 。

Defining a class

// function TodoService() {
//   this.todos = [];
// }

// TodoService.prototype.getAll = function () {
//   return this.todos;
// };

// var service = new TodoService();
// service.getAll();

//=====>
// class TodoService {
//   todos: Todo[] = [];

//   constructor(todos: Todo[]) {
//     this.todos = todos;
//   }

//   getAll() {}
// }

//=====>
class TodoService {
  constructor(private todos: Todo[]) {}

  getAll() {
    return this.todos;
  }
}

interface Todo {
  name: string;
  state: TodoState;
}

enum TodoState {
  New = 1,
  Active,
  Completed,
  Deleted,
}

Applying static properties

定义静态属性

  1. In other languages such as C#, Java, or even C, C++, you’d refer to these kinds of variables as static members.
  2. However, global variables are now generally considered bad practice and to be avoided at all costs.
  3. 所以在ES5里只能这样写:
function TodoService() {}

TodoService.lastId = 0;

TodoService.getNextId = function () {
  return (TodoService.lastId += 1);
};

TodoService.prototype.add = function (todo) {
  var newId = TodoService.getNextId();
};
  1. in ES6:
class TodoService {

  static lastId: number = 0;//静态属性
  
  constructor(private todos: Todo[]) {}

  add(todo: Todo) {
    var newId = TodoService.getNextId();
  }

  getAll() {
    return this.todos;
  }

//静态方法
  static getNextId() {
    return (TodoService.lastId += 1);
  }
}

interface Todo {
  name: string;
  state: TodoState;
}

enum TodoState {
  New = 1,
  Active,
  Completed,
  Deleted,
}

Making properties smarter with accessors

to define and substantiate证实 simply object

this code is actually perfectly legitimate合法

it must be preceded by the set keyword

let passcode = 123456;

class Employee {

  private _fullName: string; //私有变量 an internal variable

  get changeName() {
    return this._fullName;
  }

  set changeName(newName) {
    if (passcode && passcode == 123456) {
      this._fullName = newName;
    } else {
      throw "error";
    }
  }
}

Inheriting behavior from a base class

derive from源自于 a class

extends BaseClass

class TodoStateChanger {
  constructor(private newState: TodoState) {}

  canChangeState(todo: Todo): boolean {
    return !!todo;
  }

  changeState(todo: Todo): Todo {
    if (this.canChangeState(todo)) {
      todo.state = this.newState;
    }

    return todo;
  }
}

class CompleteTodoStateChanger extends TodoStateChanger {
  constructor() {
    super(TodoState.Completed); // 在派生类的构造函数中必须调用 super()
  }

  canChangeState(todo: Todo): boolean {
    return (
      super.canChangeState(todo) &&
      (todo.state == TodoState.Active || todo.state == TodoState.Deleted)
    );
  }
}

Implementing an abstract class

enforce my intent 执行我的意图

nothing stopping some rogue javascripit code from creating a new instance
没有什么能阻止一些流氓 javascripit 代码创建一个新实例

is designed to guard against, there is ultimately nothing i can do about that
旨在防范,最终我无能为力

All I can do is focus on the protection that it gives me at development time and in that regard, abstract base classes are an excellent tool.
我所能做的就是专注于它在开发时给我的保护,在这方面,抽象基类是一个很好的工具。

abstract class TodoStateChanger {
  constructor(private newState: TodoState) {}

  // canChangeState(todo: Todo): boolean {
  //   return !!todo;
  // }
  // =>改成抽象类
  abstract canChangeState(todo: Todo): boolean; // 必须在派生类中实现

  changeState(todo: Todo): Todo {
    if (this.canChangeState(todo)) {
      todo.state = this.newState;
    }

    return todo;
  }
}

class CompleteTodoStateChanger extends TodoStateChanger {
  constructor() {
    super(TodoState.Completed); // 在派生类的构造函数中必须调用 super()
  }

  canChangeState(todo: Todo): boolean {
    return (
      //super.canChangeState(todo)
      //=>
      !!todo &&
      (todo.state == TodoState.Active || todo.state == TodoState.Deleted)
    );
  }
}

Controlling visibility with access modifiers

使用访问修饰符控制可见性

abstract class TodoStateChanger {
// 抽象类中把它从private改成protected,在派生类中可以被访问到
  constructor(protected newState: TodoState) {} 
}

class CompleteTodoStateChanger extends TodoStateChanger {
  constructor() {
    super(TodoState.Completed);
    var a = this.newState // 抽象类中把它从private改成protected,在派生类中可以被访问到
  }
}
class SmartTodo {
  // name: string;
  // constructor(name: string) {
  //   this.name = name;
  // }
  // => 不用专门声明一个name,直接在构造函数里加任何修饰符public/protected/private作为声明
  constructor(public name: string) {
    this.name = name;
  }
}

私有变量加下划线

private static _lastId: number = 0;

Implementing interfaces

class TodoService implements IToDoService {
  private static _lastId: number = 0;

  get nextId() {
    return (TodoService._lastId += 1);
  }

  constructor(private todos: Todo[]) {}

  add(todo: Todo) {
    todo.id = this.nextId;
    this.todos.push(todo);
    return todo;
  }

  delete(todoId: number): void {
    var toDelete = this.getById(todoId);
    var deletedIndex = this.todos.indexOf(toDelete);
    this.todos.splice(deletedIndex, 1);
  }

  getAll(): Todo[] {
    // 不直接return Todo数组出去
    // 现在互联网传输的数据一般都是json格式
    // 将数据传出去之前,先用JSON.stringify把数据转成json字符串格式,方便传输
    // 否则得到的是[object object]
    // 接收到数据后,用JSON.parse把数据转成对象格式以便本地使用
    var clone = JSON.stringify(this.todos);
    return JSON.parse(clone);
  }

  getById(todoId: number): Todo {
    //JS's built-in array method filter JS的内置的数组过滤方法
    var filtered = this.todos.filter((i) => i.id == todoId); 
   
    if (filtered.length) {
      return filtered[0];
    }
    return null;
  }
}

interface IToDoService {
  add(todo: Todo): Todo;
  delete(todoId: number): void;
  getAll(): Todo[];
  getById(todoId: number): Todo;
}

interface Todo {
  id: number;
  name: string;
  state: TodoState;
}

enum TodoState {
  New = 1,
  Active,
  Completed,
  Deleted,
}

no, quite the contrary 不,恰恰相反
icing on the cake 锦上添花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值