TypeScript与面向对象
1、引
简而言之就是程序之中所有的操作都需要通过对象来完成。一切操作都要通过对象,也就是所谓的面向对象,在程序中对象被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高等属于数据,人可以说话、走路、吃饭、睡觉这些都属于人的功能,数据在对象中被称为属性,而功能被称为方法,所以简而言之在程序中一切皆对象
2、类(class)
// 使用class关键字来定义一个类
/*
* 对象中主要包含了两个部分:
* 属性
* 方法
* */
class Person{
/*
* 直接定义的属性是实例属性,需要通过对象的实例去访问:
* const per = new Person();
* per.name
*
* 使用static开头的属性是静态属性(类属性),可以直接通过类去访问
* Person.age
*
* readonly开头的属性表示一个只读的属性无法修改
* */
// 定义实例属性
// readonly name: string = '孙悟空';
name = '孙悟空';
// 在属性前使用static关键字可以定义类属性(静态属性)
// static readonly age: number = 18;
age = 18;
// 定义方法
/*
* 如果方法以static开头则方法就是类方法,可以直接通过类去调用
* */
sayHello(){
console.log('Hello 大家好!');
}
}
const per = new Person();
// console.log(per);
// console.log(per.name, per.age);
// console.log(Person.age);
// console.log(per.name);
// per.name = 'tom';
// console.log(per.name);
// per.sayHello();
// Person.sayHello();
per.sayHello();
readonly 表示一个只读属性,不能修改,是在实例上的
static 表示一个静态属性,通过类的点语法
3、构造函数和this
class Dog{
name: string;
age: number;
// constructor 被称为构造函数
// 构造函数会在对象创建时调用
constructor(name: string, age: number) {
// 在实例方法中,this就表示当前当前的实例
// 在构造函数中当前对象就是当前新建的那个对象
// 可以通过this向新建的对象中添加属性
this.name = name;//第一个name是类的属性,第二个name是传进的参数的类型
this.age = age;
}
bark(){
// alert('汪汪汪!');
// 在方法中可以通过this来表示当前调用方法的对象
console.log(this.name);
}
}
const dog = new Dog('小黑', 4);
const dog2 = new Dog('小白', 2);
// console.log(dog);
// console.log(dog2);
dog2.bark();
4、继承
(function (){
// 定义一个Animal类
class Animal{
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello(){
console.log('动物在叫~');
}
}
/*
* Dog extends Animal
* - 此时,Animal被称为父类,Dog被称为子类
* - 使用继承后,子类将会拥有父类所有的方法和属性
* - 通过继承可以将多个类中共有的代码写在一个父类中,
* 这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法
* 如果希望在子类中添加一些父类中没有的属性或方法直接加就行
* - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法,方法可以重写!!
* 这种子类覆盖掉父类方法的形式,我们称为方法重写
*
* */
// 定义一个表示狗的类
// 使Dog类继承Animal类
class Dog extends Animal{
run(){
console.log(`${this.name}在跑~~~`);
}
sayHello() {
console.log('汪汪汪汪!');
}
}
// 定义一个表示猫的类
// 使Cat类继承Animal类
class Cat extends Animal{
sayHello() {
console.log('喵喵喵喵!');
}
}
const dog = new Dog('旺财', 5);
const cat = new Cat('咪咪', 3);
console.log(dog);
dog.sayHello();
dog.run();
console.log(cat);
cat.sayHello();
})();
5、super
子类写了constructor构造函数必须使用super继承父类constructor构造函数的属性
(function () {
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('动物在叫~');
}
}
class Dog extends Animal{
age: number;
constructor(name: string, age: number) {
// 如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数进行调用
//super(name) === this.name = name,伪代码
super(name); // 调用父类的构造函数
//如果在子类的构造函数直接super父类构造函数
this.age = age;
}
// 重写父类方法
sayHello() {
// 在类的方法中 super就表示当前类的父类
// super.sayHello();
console.log('汪汪汪汪!');
}
}
const dog = new Dog('旺财', 3);
dog.sayHello()
})();
6、抽象类
(function () {
/*
* 以abstract开头的类是抽象类,
* 抽象类和其他类区别不大,只是不能用来创建对象
* 抽象类就是专门用来被继承的类
*
* 抽象类中可以添加抽象方法
* */
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
// 定义一个抽象方法
// 抽象方法使用 abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello():void;
}
class Dog extends Animal{
sayHello() {
console.log('汪汪汪汪!');
}
}
class Cat extends Animal{
sayHello() {
console.log('喵喵喵喵!');
}
}
const dog = new Dog('旺财');
dog.sayHello();
})();
抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
7、接口
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
示例(检查对象类型):
interface Person{
name: string;
sayHello():void;
} function fn(per: Person){
per.sayHello();
} fn({name:'孙悟空', sayHello() {console.log(`Hello, 我是 ${this.name}`)}});
示例(实现)
interface Person{
name: string;
sayHello():void;
} class Student implements Person{
constructor(public name: string) {
} sayHello() {
console.log('大家好,我是'+this.name);
}
}
8、属性的封装
- public
- 修饰的属性可以再任意位置访问修改默认值
- private
- 私有属性,私有属性只能在类内部进行访问修改
- protected
- protected受包含的属性,只能在当前类和当前类的子类中访问
- getter方法用来读取属性
- setter方法迎来设置属性
- getter和setter被统一称为属性的存储器,定义时在方法之前添加get和set,调用的时候直接通过点语法调用
(function (){
// 定义一个表示人的类
class Person{
// TS可以在属性前添加属性的修饰符
/*
* public 修饰的属性可以在任意位置访问(修改) 默认值
* private 私有属性,私有属性只能在类内部进行访问(修改)
* - 通过在类中添加方法使得私有属性可以被外部访问
* protected 受包含的属性,只能在当前类和当前类的子类中访问(修改)
*
* */
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
/*
* getter方法用来读取属性
* setter方法用来设置属性
* - 它们被称为属性的存取器
* */
// TS中设置getter方法的方式
get name(){
// console.log('get name()执行了!!');
return this._name;
}
set name(value){
this._name = value;
}
get age(){
return this._age;
}
set age(value){
if(value >= 0){
this._age = value
}
}
}
const per = new Person('孙悟空', 18);
/*
* 现在属性是在对象中设置的,属性可以任意的被修改,
* 属性可以任意被修改将会导致对象中的数据变得非常不安全
* */
// per.setName('猪八戒');
// per.setAge(-33);
per.name = '猪八戒';
per.age = -33;
// console.log(per);
class A{
//protected是保护的属性,只能在当前类和子类中设置
//protected只能在当前类和当前类的子类中设置
protected num: number;
constructor(num: number) {
this.num = num;
}
}
class B extends A{
test(){
console.log(this.num);
}
}
const b = new B(123);
// b.num = 33;
/* class C{
name: string;
age: number
// 可以直接将属性定义在构造函数中
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}*/
class C{
// 直接将属性定义在构造函数中
constructor(public name: string, public age: number) {
}
}
const c = new C('xxx', 111);
console.log(c);
})();
9、泛型
定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、属性、参数的类型不能确定),此时泛型便能通够发挥作用
function test(arg:any):any{
return arg
}
在这个例子中,test函数又一个参数类型不确定,但是能确定的是其返回值的类型和参数的类型是相同的,由于类型不确定所有参数和返回值均使用了any,但是很明显这样做是不合适的,首先使用any会关闭TS的类型检查,其次这样设置也不能体现出参数和返回值是相同的类型
通过泛型来确认参数和返回值的类型相同
function test<T>(arg:T):T{
return arg
}
这里的
<T>
就是泛型,T是我们给这个类型起的名字(不一定必须叫T),设置泛型后即可在函数中使用T来表示该类型。所以泛型其实很好理解,就表示某个类型
那么如何使用上面的函数呢?
方式一(直接使用)
test(10)//直接使用
使用时直接传递参数使用,类型会由TS自动推断出来,但有时编译器无法自动判断时还需要使用下面的方式
方式二(指定类型)
也可以在函数后手动指定泛型
可以同时指定多个泛型,泛型间使用逗号隔开
function test<T,K>(a:T,B:K):K {
return b
}
test<number,string>(10,"hello")
使用泛型时,完全可以将泛型当成是一个普通的类去使用
类中同样可以使用泛型
class MyClass<T>{
prop:T
constructor(prop:T){
this.prop = prop
}
}
除此之外,也可以对泛型的范围进行约束
interface MyInter{
length: number;
} function test<T extends MyInter>(arg: T): number{
return arg.length;
}
使用T extends MyInter表示泛型T必须是MyInter的子类,不一定非要使用接口类和抽象类同样适用。
TypeScript与面向对象的更多相关文章
- TypeScript之面向对象初体验
1.安装nodejs和vscode: nodejs : https://nodejs.org/en/ Visual Studio Code : https://www.visualstudio.co ...
- Typescript的面向对象
封装: var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.prot ...
- JavaScript面向对象轻松入门之概述(demo by ES5、ES6、TypeScript)
写在前面的话 这是一个JavaScript面向对象系列的文章,本篇文章主要讲概述,介绍面向对象,后面计划还会有5篇文章,讲抽象.封装.继承.多态,最后再来一个综合. 说实话,写JavaScript面向 ...
- TypeScript学习笔记(一):介绍及环境搭建
官网 TypeScript目前还在快速的发展中,当前的版本是1.6,有关TypeScript更多的信息可以在其官网中获取. http://www.typescriptlang.org/ 什么是Type ...
- 为什么选择Typescript
上一节,我简单介绍了Typescript,并将Typescript和JavaScript进行了对比,有些网友提出了一些疑问,可能有些网友对于这个Typescript还不是特别的熟悉,这节,我做一些演示 ...
- TypeScript入门教程
TypeScript是什么 TypeScript是JavaScript的一个超集 TypeScript需要编译为JavaScript才能运行(语法糖) TypeScript提供了类型系统,规范类似Ja ...
- TypeScript 学习笔记(三)
类: 1.TypeScript 是面向对象的 JavaScript,类描述了创建的对象共同的属性和方法 2.类通过关键字 class 声明,使用 extends 关键字进行继承 3.在引用一个类成员时 ...
- typeScript学习随笔(一)
TypeScript学习随笔(一) 这么久了还不没好好学习哈这么火的ts,边学边练边记吧! 啥子是TypeScript TypeScript 是 JavaScript 的一个超集,支持 es6 标准 ...
- TypeScript作为前端开发你必须学习的技能(一)
2019年,TypeScript已经开始渐渐的崭露头角,各大框架都说要使用TypeScript,虽然现在还没有完美,但是TypeScript很有可能会成为下一个主流技术. 废话就不多说了,直接开始吧. ...
随机推荐
- Qt Designer中自定义控件的使用(提升法与插件法)
准备乱写一点Qt自定义Widget在Designer中的使用.可是又不想重复提升法(promotion)及插件法基本用法,因为Manual中Using Custom Widgets with Qt D ...
- MySQL学习01(初识MySQL)
初识MySQL 只会写代码的是码农:学好数据库,基本能混口饭吃:在此基础上再学好操作系统和计算机网络,就能当一个不错的程序员.如果能再把离散数学.数字电路.体系结构.数据结构/算法.编译原理学通透,再 ...
- Golang语言系列-12-网络编程
网络编程 互联网协议介绍 互联网的核心是一系列协议,总称为"互联网协议"(Internet Protocol Suite),正是这一些协议规定了电脑如何连接和组网.我们理解了这些协 ...
- kali虚拟机安装VMTools、更新源、安装docker、配置sqli-labs
一.安装VMTools: 传送门:关于安装VMTools 跟其他版本的虚拟机安装VMTools没什么区别,也得连网(我是kali用dhcp开nat模式) 之后按照上面的链接根据博主的步骤一步一步来即可 ...
- JIT-动态编译与AOT-静态编译:java/ java/ JavaScript/Dart乱谈
C 和 C++ 之类的编译语言性能远超Java,但是生成的代码只能在有限的几种系统上执行,这就有了Java的存在基础(JVM-跨平台) 早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之 ...
- Nikitosh 和异或
题面 设 \(l_{i}\) 为以 \(i\) 为结尾的区间中最大的一段异或值,\(r_{i}\) 为以 \(i\) 为开头的区间中最大的一段异或值. 则有 \[l_{i}=\max\left(l[i ...
- NOIP 模拟 $31\; \rm Game$
题解 很容易求出在没有字典序最大的限制条件下的最多胜利场数. 这样就可以对于每一位放最优的解,怎么做,二分答案. 分两种情况,一种是当前一位是输的,一种是赢的,复杂度 \(\mathcal O(\rm ...
- flutter学习资料汇总
1.https://github.com/chinabrant/flutter_study 2.https://github.com/zhujian1989/flutter_study 3.https ...
- WPF中实现动画的几种效果(最基础方式)
参考网址:https://blog.csdn.net/qq_45096273/article/details/106256397 在动画之前我们先了解一下几个声明式动画中常用的元素: 一.Storyb ...
- mybatis学习日志二
一.动态sql语句 if语句 if+where语句 if+set语句 choose(when,otherwise)语句 trim语句 sql片段 foreach语句 总结 bean部分的User类代码 ...