ts 学习笔记 - 类
类
类的概念
- 类 (class) : 定义了意见事物的抽象特点,包含它的属性和方法
- 对象 (Object) :类的实例,通过
new生成 - 面对对象 (OOP) 的三大特性: 封装、继承、多态
- 封装 (Encapsulation):将对数据的操作细节隐藏起来,值暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
- 继承 (Inheritance): 子类继承父类, 子类除了拥有父类的所有特性外, 还有一些更具体的特性
- 多态 (Polymorphism):由继承二产生了相关的不同的类,对同一个方法可以有不同的响应。比如
Cat和Dog都是继承自Animal, 但是分别实现了自己的eat方法。此时针对某一个实例,我们无需了解它是Cat还是Dog, 就可以直接调用eat方法, 程序会自动判断出来应该如何执行eat - 存取器 (getter & setter):用来改变属性的读取和赋值行为
- 修饰符 (Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如
public表示公有属性或方法 - 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中抽象方法避税在子类中被实现
- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类, 但是可以实现多个接口
类的用法
属性和方法
使用 class 定义类, 使用 constructor 定义构造函数。
通过 new 生成新实例的时候, 会自动调用构造函数。
class Animal {
constructor(name) {
this.name = name
}
sayHi() {
return `My name is ${this.name}`
}
}
let a = new Animal('jack')
console.log( a.sayHi() ) // My name is Jack
类的继承
使用 extends 关键字实现继承, 子类中使用 super 关键字来调用父类的构造函数和方法。
class Cat extends Animal {
constructor(name) {
super(name) // 调用父类的 constructor(name)
console.log(this.name)
}
sayHi() {
return 'Meow, ' + super.sayHi() // 调用父类的 sayHi()
}
}
let c = new Cat('Tom') // Tom
console.log(c.sayHi()) // Meow, My name is Tom
存取器
使用 getter 和 setter 可以改变属性的赋值和读取行为:
class Animal {
constructor(name) {
this.name = name
}
get name() {
return 'Jack'
}
set name(value) {
console.log('setter: ' + value)
}
}
let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack
静态属性
到目前为止,我们只讨论了类的实例成员,哪些仅当类被梳理化的时候才会被初始化的属性。
使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用。
下例中,我们实现一个网格类, 通过 calculateDistanceFromOrigin 方法来当前点计算到原点的距离。
class Grid {
static origin = { x: 0, y: 0 }
scale: number
constructor(scale: number) {
this.scale = scale
}
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
}
}
let grid1 = new Grid(1.0) // scale => 1
let grid5 = new Grid(5.0) // scale => 5
grid1.calculateDistanceFromOrigin({x: 3, y: 4})
grid5.calculateDistanceFromOrigin({x: 3, y: 4})
Typescript 中的用法
public, private, protected
Typescript 中可以使用三种访问修饰符(Access Modifiers),分别是 public, private, protected 。
public修饰的属性或方法都是公有的, 在任何地方都可以访问到。默认的所有属性和方法都是public的 。private修饰的属性或方法都是私有的,不能再申明它的类的外部去访问。protected修饰的属性或方法是受保护的,它和private类似, 区别是它的子类中也是允许被访问。
class Person {
public name
public constructor(name) {
this.name = name
}
}
let p = new Person('Jack')
console.log(p.name) // Jack
p.name = 'Tom'
console.log(p.name) // Tom
上面的例子中 name 被设置了 public , 所以直接访问 name 是被允许的。
很多时候,我们希望有的属性是无法在外部直接存取。 这时候就需要用到 private 。
class Person {
private name
constructor(name) {
this.name = name
}
}
let p = new Person('Jack')
console.log(p.name) // Jack
p.name = 'Tom' // err Property 'name' is private...
使用 private 修饰的属性或方法,在子类中也是不允许访问的:
class Person {
private name
constructor(name) {
this.name = name
}
}
class Male extends Person {
constructor(name) {
super(name)
console.log(this.name)
}
}
// err
需要注意的是,TypeScript 编译之后的代码中,并没有限制 private属性在外部的可访问性。
而如果是用 protected 修饰, 怎允许在子类中访问:
class Animal {
protected name;
public constructor(name) {
this.name = name;
}
}
class Cat extends Animal {
constructor(name) {
super(name);
console.log(this.name);
}
}
抽象类
abstract 用于定义抽象类和其中的抽象方法。
什么是抽象类?
首先抽象类不允许实例化,
abstract class Persong {
public name
public constructor(name) {
this.name = name
}
public abstract sayHi()
}
let p = new Person('Jack') // err
上面的例子中,我们定义了一个抽象类 Animal,并且定义了一个抽象方法 sayHi。在实例化抽象类的时候报错了。
其次,抽象类中的抽象方法必须被子类实现:
abstract class Person {
constructor(name) {
this.name = name
}
public abstract sayHi()
}
class Male extends Persong {
public eat() {
console.log(`${this.name} is eating.`)
}
}
let Jack = new Male('jack') // err Male 中 并没有实现 Perosn 中的 sayHi 方法
上例中由于 Male 中没有实现 父类 Person 中的 sayHi 方法, 所以 编译报错
abstract class Person {
constructor(name) {
this.name = name
}
public abstract sayHi()
}
class Male extends Persong {
public sayHi() {
console.log(`Meow, My name is ${this.name}`)
}
}
let Jack = new Male('jack') // success
类的类型
类的类型 与接口相似
class Person {
name: sting
constructor(name: sting) {
this.name = name
}
sayHi(): string {
return `My name is ${this.name}.`
}
}
let p: Person = new Person('Jack')
console.log(a.sayHi()) // My name is Jack
类与接口
类实现接口
实现(implements)是面对对象中一个很重要的概念。一般来讲,一个类只能继承自另外一个类,有的时候不同类之间存在着一些可以共用的特性,这时可以把这些特性提取成接口 (interfaces),用 implements 关键字来实现。
举例来说,门是一个类, 防盗门是门的子类。如果防盗门有报警功能, 这时我们可以简单的给防盗门添加一个报警的方法。这时候如果有另一类, 车。 车子也需要有报警功能。此时就可以考虑吧报警器这个功能提取出来, 作为一个接口,防盗门和车都去实现它。
interface Alarm {
alert()
}
class Door {
}
class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert')
}
}
class Car implements Alarm {
alert() {
console.log('Car alert')
}
}
一个类可以实现多个接口:
interface Alarm {
alert()
}
interface Light {
lightOn()
lightOff()
}
class Car implements Alarm, Light {
alert() {
console.log('Car alert')
}
lightOn() {
console.log('Car light on')
}
lightOff() {
console.log('Car light off')
}
}
上面的例子中, Car 实现了 Alarm, Light 接口, 既能报警, 也能开关车灯。
接口继承接口
接口与接口之间可以是继承关系:
通过使用 extends 来继承
interface Alarm {
alert()
}
interface Light extends Alarm {
lightOn()
lightOff()
}
class Car implements Light {
alert() {
console.log('Car alert')
}
lightOn() {
console.log('Car light on')
}
lightOff() {
console.log('Car light off')
}
}
接口继承类
接口也可以继承类:
class Point {
x: number
y: number
}
interface Point3D extends Poing {
z: number
}
let point3d: Point3D = {x: 1, y: 2, z: 3}
混合类型
我们知道,可以使用接口的方式来定义一个函数需要符合的形状:
interface SearchFunc {
(source: string, subString: string): boolean
}
let mySearch: SearchFunc
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1
}
有时候,一个函数还可以有自己的属性和方法:
interface Counter {
(start: number): string
interval: number
reset(): void
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { }
counter.interval = 123
counter.reset = function () { }
return counter
}
let c = getCounter()
c(10)
c.reset()
c.interval = 5.0
ts 学习笔记 - 类的更多相关文章
- 《python基础教程(第二版)》学习笔记 类和对象(第7章)
<python基础教程(第二版)>学习笔记 类和对象(第7章) 定义类class Person: def setName(self,name): self.name=n ...
- Java学习笔记--类和对象
1.介绍面向对象的编程 面向对象是现在主流的编程样例,它替代了以前C语言使用时的“结构体”,Java是一门面向对象的语言,所以需要熟悉面向对象的概念.面向对象的程序由很多对象组成,每 ...
- ts 学习笔记-基础篇
目录 基础 原始数据类型 布尔值 数字 字符串 空值 Null 和 Undefined 任意值 类型推论 联合类型 接口 数组 函数 类型断言 申明文件 什么是申明文件 三斜线指令 第三方声明文件 内 ...
- Objective-C学习笔记类目、协议
不是所有的方法都可以被覆盖的!比如:intValue就不能被覆盖!! 原因正在查找中! 别人的电脑上却可以! 类目.h件 #import <Foundation/Foundation.h> ...
- scala学习笔记——类和对象
基础语法关于Scala程序,这是非常要注意以下几点. 区分大小写 - Scala是大小写敏感的,这意味着标识Hello 和 hello在Scala中会有不同的含义. 类名 - 对于所有的类名的第一个字 ...
- java 学习笔记——类之间的关系之封装、继承与多态的详解
封装 一个封装的简单例子 封装就是把对象的属性(状态)和方法(行为)结合在一起,并尽可能隐蔽对象的内部细节,成为一个不可分割的独立单位(即对象),对外形成一个边界,只保留有限的对外接口使之与外部发生联 ...
- Java编程思想学习笔记——类的访问权限
类的访问权限 Java中,访问权限修饰词用于确定库中哪些类对于该库的使用者是可用的. public class Foo{ } 注意点: 每个文件(编译单元)只能有一个public类. public类的 ...
- 廖雪峰Python学习笔记——类和实例
Class MyList(list): __metaclass__ = ListMetaclass #它表示在创建MyList这个类时,必须通过 ListMetaclass这个元类的LIstMetac ...
- C++学习笔记-类相关问题总结
1.默认构造函数 默认构造函数要么没有参数,要么所有参数都有默认值.如果没有定义任何构造函数,编译器将自定义默认构造函数. 自动生成的默认的构造函数的作用: (1)使可以创建对象 (2)调用基类的默认 ...
随机推荐
- NX二次开发-创建(临时)坐标系
函数:UF_CSYS_create_csys() . UF_CSYS_create_temp_csys() 函数说明:创建坐标系 .创建临时坐标系 用法: #include <uf.h> ...
- Etcd中linearizable read实现
linearizable 有点疑惑,不确定是现在浏览的版本没开发完全,还是没有按照论文的linearizable来实现. 按照论文所说,在客户端请求的时候,实际上是一个强一致的 exactly onc ...
- git 认证问题之一的解决 : http ssh 互换
场景 使用git 我们经常会遇到 认证失败的情况,有时候确实是搞错了用户名或者密码,还有的时候及时用户名密码用对了也还是认证失败. 此时, 就有可能是下面这个情况. 没有配置 ssh 秘钥, 而用了 ...
- 【带你手撸Spring】没有哪个框架开发,能离开 Spring 的 FactoryBean!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老司机,你的砖怎么搬的那么快? 是有劲?是技巧?是后门?总之,那个老司机的代码总是可 ...
- 用 .SqlSugar ORM 来实现报表功能 .NET CORE /.NET
架框介绍 SqlSugar是一款.NET老牌ORM 并且也是 新手基数比较多的ORM(因为上手容易),SqlSugar之所以能一直更新到现在,还是要感谢SqlSugar的忠实用户,随着我的技术越来越好 ...
- 重新整理 .net core 实践篇————cookie 安全问题[三十八]
前言 简单整理一下cookie的跨站攻击,这个其实现在不常见,因为很多公司都明确声明不再用cookie存储重要信息,不过对于老站点还是有的. 正文 攻击原理: 这种攻击要达到3个条件: 用户访问了我们 ...
- CentOS-Docker安装RabbitMQ集群(rabbitmq:3.7.16-management)
准备工作 1.机器资源(分别安装docker环境) 建议机器配置: centos7.x 4G及以上 100GB及以上 2核及以上 192.168.1.101 192.168.1.102 192.168 ...
- 14 shell 函数
1.shell函数的定义与调用 2.shell函数参数 3.函数返回值 1.shell函数的定义与调用 Shell 函数定义 说明 函数定义的简化写法 函数调用 function name() { ...
- K8S(Kubernetes)学习笔记
Kubernetes(k8s)是google提供的开源的容器集群管理系统,在Docker技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理 ...
- 协程与Swoole的原理,相关应用以及适用场景等
什么是协程 协程(Coroutine)也叫用户态线程,其通过协作而不是抢占来进行切换.相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低.协程是进程的补充,或者是互补关系. 要 ...