首页 > 其他分享 >41 Typescript面向对象

41 Typescript面向对象

时间:2024-04-13 17:25:35浏览次数:23  
标签:Typescript name age number 41 面向对象 实例 属性 string

简介

程序之中所有的操作都需要通过对象来完成

举例来说:

  • 操作浏览器要使用window对象
  • 操作网页要使用document对象
  • 操作控制台要使用console对象

一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是什么,计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人、一条狗、一把枪、一颗子弹等等所有的事物。一个事物到了程序中就变成了一个对象。

在程序中所有的对象都被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能。

数据在对象中被成为属性,而功能就被称为方法。所以简而言之,在程序中一切皆是对象

类class

要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象,举例来说:可以通过Person类来创建人的对象,通过Dog类创建狗的对象,通过Car类来创建汽车的对象,不同的类可以用来创建不同的对象。

定义类--语法

class 类名 {
	属性名: 类型;

	constructor(参数: 类型){
		this.属性名 = 参数;
	}

	方法名(){
		....
	}
}

属性

类属性可以分为2类:实例属性和类属性

实例属性

直接定义的属性就是实例属性,必须通过类的实例对象去访问

<script lang="ts" setup>
class Person {
  // 定义实例属性:要想访问实例属性,必须创建一个实例对象
  name: string = '初始姓名';  # 简写为 name="初始姓名"
  age: number = 18; # 简写为:age=18
}

// 创建一个实例对象
const p = new Person();
console.log(p.name, p.age);
</script>

类属性

静态属性:也称为类属性,使用静态属性无需创建实例 ,通过类即可直接使用,但是需要在属性的前面使用static关键字定义
声明静态属性后,实例对象就不可以访问到这个类属性啦

<script lang="ts" setup>
class Person {
  // 定义实例属性
  name: string = '初始姓名';

  // 定义类属性
  static age: number = 18;
}
// 创建一个实例对象
const p = new Person();
// 实例对象只能访问name,不可以访问age,因为age是类属性
console.log(p.name);

// age声明了静态属性,所以可以直接访问
console.log(Person.age);
</script>

如果是 readonly开头的属性,表示的是一个只读属性,不可以修改

// 定义类属性
readonly age: number = 18;

方法

同类属性一个,如果方法的前面添加上 static ,就是类方法

<script lang="ts" setup>
class Person {
  name: string = '初始姓名';
  age: number = 18;

  // 方法
  sayHello() {
    console.log('你好');
  }
}
// 创建一个实例对象
const p = new Person();
// 访问实例方法
p.sayHello();
</script>

构造函数和this

constructor 是构造函数的关键字,构造函数会在对象创建时调用,每创建一次对象,构造函数就会被调用一次
实例对象的传参主要是通过类的构造函数接收的

指向

在构造函数中,this当前对象就是当前创建的那个实例对象
在方法中,this当前对象就是当前调用这个方法的实例对象

<script lang="ts" setup>
class Person {
  name: string = '初始姓名'; // 初始化默认值
  age: number = 18;

  // 构造函数 constructor,构造函数会在对象创建实例时调用
  constructor(name1: string, age1: number) {
    this.name = name1;
    this.age = age1;
    // 在实例方法中,当前的this表示的当前创建的那个实例对象
    console.log(this, 'this对象');
  }
  
  // 方法
  sayHello() {
    # 在方法中,当前对象this就是调动方法的那个实例对象 
    console.log('你好', this.name);
  }
}
// 创建一个实例对象p1
const p1 = new Person('张三', 18);
// 创建一个实例对象p2
const p2 = new Person('李四', 28);

console.log(p1); // name=张三 age=18
console.log(p2); // name=李四 age=28
</script>

继承

通过继承可以将其他类中的属性和方法引入到当前类中

通过继承可以在不修改类的情况下实现对类的扩展,子类将会拥有父类的所有属性和方法

继承所有属性和方法

<script lang="ts" setup>
// 创建动物类
class Animal {
  name: string;
  age: number;
  helloTxt: string;

  // 构造函数
  constructor(name: string, age: number, helloTxt: string) {
    this.name = name;
    this.age = age;
    this.helloTxt = helloTxt;
  }
  // 方法
  sayHello() {
    console.log(`你好呀,我是${this.name},我今年${this.age}岁啦,我会${this.helloTxt}`);
  }
}

// 创建一个 Dog类,同时继承 Animal类
class Dog extends Animal {}

// 创建一个 Cat类,同时继承 Animal类
class Cat extends Animal {}

// 实例化Dog对象,创建一个Dog实例dog
const dog = new Dog('小黑', 5, '汪汪汪!!!');

// 实例化Dog对象,创建一个Cat实例cat
const cat = new Cat('喵喵', 3, '喵喵喵~~~');

dog.sayHello();
cat.sayHello();
</script>


重写方法

如果在子类中添加了和父类相同的方法,那么子类的方法会覆盖父类的方法,这种子类覆盖掉父类的形式,就是方法的重写

<script lang="ts" setup>
// 创建动物类
class Animal {
  name: string;
  age: number;

  // 构造函数
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  // 方法
  sayHello() {
    console.log(`你好呀,我是${this.name},我今年${this.age}岁啦`);
  }
}

// 创建一个 Dog类,同时继承 Animal类,此时子类将拥有父类所有的属性和方法
// 同时也可以自己定义类的独有属性和方法
class Dog extends Animal {
  // 定义自己独有的属性
  run() {
    console.log(`${this.name}在跑步,我会汪汪汪~~~`);
  }
  // 如果在子类中添加了和父类相同的方法,那么子类的方法会覆盖父类的方法,这种子类覆盖掉父类的形式,就是方法的重写
  sayHello() {
    console.log('汪汪汪~~~');
  }
}

// 创建一个 Cat类,同时继承 Animal类
class Cat extends Animal {}

// 实例化Dog对象,创建一个Dog实例dog
const dog = new Dog('小黑', 5);
dog.run(); // 调用独有方法
dog.sayHello(); // 调动重写的方法

// 实例化Dog对象,创建一个Cat实例cat
const cat = new Cat('喵喵', 3);
cat.sayHello(); // 调用父类的方法
</script>

super 关键字

在子类重写方法的时候,super 就表示当前类的父类

在子类构建自己的构造函数的时候,必须要重新调用一次父类的构造函数

<script lang="ts" setup>
// 创建动物类--父类
class Animal {
  // 属性
  name: string;
  age: number;

  // 构造函数
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  // 方法
  sayHello() {
    console.log(`你好呀,我是${this.name},我今年${this.age}岁啦`);
  }
}

// 创建一个 Dog类,继承 Animal类
class Dog extends Animal {
  // 构建自己的独有属性
  color: string;

  // 如果在子类中写了构造函数,也会对父类中的构造函数进行重写,所以在子类中必须要重新调用一次父类的构造函数
  constructor(name: string, age: number, color: string) {
  // 重新调用父类的构造函数
    super(name, age); 
    this.color = color;
  }

  // 重写父类
  sayHello() {
    // 此类的方法中 super 就表示当前类的父类,所以可以直接调用父类中所有的方法--一般不推荐这样写,而是重新重写自己的方法
    // super.sayHello();

    // 重写自己的方法
    console.log(`你好呀,我是${this.name},我今年${this.age}岁啦,我是${this.color}`);
  }
}

// 实例化Dog对象
const dog = new Dog('小黑', 5, '白色的');
dog.sayHello(); // 调动重写的方法
</script>

抽象类-abstract

抽象类是专门用来被其他类所继承的类它只能被其他类所继承不能用来创建实例,即只能被继承,不能创建一个实例

抽象类中可以定义普通方法,也可以定义抽象方法

抽象方法

  • 只能在抽象类中定义
  • 在方法的前面添加关键字 abstract
  • 一旦在抽象类中定义了抽象方法,那么继承它的子类,必须重写实现抽象方法
<script lang="ts" setup>
// 创建抽象类 abstract
abstract class Animal {
  // 属性
  name: string;

  // 构造函数
  constructor(name: string) {
    this.name = name;
  }
  // 定义一个 返回值为空的抽象方法
  // 抽象方法使用 abstract开头,没有方法体
  // 抽象方法只能定义抽象类中,而且子类必须对抽象方法进行重写
  abstract sayHello(): void;
}

// 创建一个子类,同时继承 父类
class Dog extends Animal {
  // 因为父类是一个抽象类,而且定义了抽象方法,所以在子类中,必须重写父类的抽象方法
  sayHello() {
    console.log(`我是${this.name}`);
  }
}

// 实例化Dog对象
const dog = new Dog('小黑');
dog.sayHello();
</script>

接口--interface

自定义 type

<script lang="ts" setup>
type myStudentType = {
  name: string;
  age: number;
};

let obj1: myStudentType = {
  name: '张三',
  age: 18,
};
let obj2: myStudentType = {
  name: '李四',
  age: 20,
};

console.log(obj1);
console.log(obj2);
</script>

1. 接口当做类型声明使用

接口可以用来定义类的结构:属性和方法,可以当做类型声明使用

<script lang="ts" setup>
interface myStudentType {
  name: string;
  age: number;
}

let obj1: myStudentType = {
  name: '张三',
  age: 18,
};
let obj2: myStudentType = {
  name: '李四',
  age: 20,
};

console.log(obj1);
console.log(obj2);
</script>

重名的接口会自动合并,接口可以重命名

<script lang="ts" setup>
interface myStudentType {
  name: string;
  age: number;
}

// 重名的接口会自动合并
interface myStudentType {
  gender: '男' | '女';
}

let obj: myStudentType = {
  name: '张三',
  age: 18,
  gender: '男',
};

console.log(obj);
</script>

2. 接口限制类的结构

  • 接口可以在定义中限制类的结构,不考虑实际值
  • 接口中所有的属性,不可以有实际值
  • 接口中定义的所有方法都是抽象方法,实例对象必须重载实现接口中的方法
实现接口-implements
<script lang="ts" setup>
// 定义一个接口
// 只限制类的结构
interface myInterface {
  name: string;
  age: number;
  sayHello(): void;
}

// 实现 implements 接口
// 接口中的 方法都是抽象方法,类必须重写
class MyStudent implements myInterface {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log('哈哈哈');
  }
}

let s = new MyStudent('小明', 30);
console.log(s);
</script>

接口和自定义类型的区别

接⼝可以:

  1. 当⾃定义类型去使⽤;
  2. 可以限制类的结构;

⾃定义类型:

  1. 仅仅就是⾃定义类型;

接口和抽象类的区别

抽象类:

  1. 可以有普通⽅法,也可以有抽象⽅法;
  2. 使⽤ extends 关键字去继承抽象类;

接⼝:

  1. 只能有抽象⽅法;
  2. 使⽤ implements 关键字去实现接⼝

属性修饰符

主要所用是确保属性的安全

名称 属性 作用
readonly 只读属性 属性是只读的,无法修改
public 公开的 可以在类、子类、对象中访问和修改
private 私有的 只能在类内部访问和修改
protected 受保护的 只能在当前类和当前类的子类中访问和修改

公开属性

简写类的声明

<script lang="ts" setup>
class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

// 如果是使用了 public 修饰符,上面类的定义可以简写为:
class Person2 {
  constructor(public name: string, public age: number) {}
}
</script>

私有属性

<script lang="ts" setup>
class Person {
  // 定义一个私有属性:name---只能在类的内部访问和修改,即只能在Person中访问和修改
  private name: string;

  constructor(name: string) {
    this.name = name;
  }

  // 定义一个get方法,向外暴露该方法,可以【访问】私有属性
  getName() {
    return this.name;
  }

  // 定义一个set方法,向外暴露该方法,可以【修改】私有属性
  setName(x: string) {
    // 此处就可以做一些数据安全的设置啦。。。。
    this.name = x;
  }
}
const p = new Person('哈哈哈');
p.setName('嘿嘿嘿');
console.log(p.getName()); // 输出为:嘿嘿嘿
</script>

</script>

getter 和 setter 存取器

<script lang="ts" setup>
class Person {
  // 定义一个私有属性:name---只能在类的内部访问和修改,即只能在Person中访问和修改
  private _name: string;
  private _age: number;

  constructor(name: string, age: number) {
    this._name = name;
    this._age = age;
  }

  // 定义一个getter和setter 存取器
  get name() {
    return this._name;
  }

  set name(value: string) {
    this._name = value;
  }

  // 定义一个getter和setter 存取器
  get age() {
    return this._age;
  }

  set age(value: number) {
    this._age = value;
  }
}
const p = new Person('哈哈哈', 18);
p.name = '嘿嘿嘿';
p.age = 28;
console.log(p); // 输出为:嘿嘿嘿 28
</script>

泛型

定义一个函数或类时,无法明确具体类型(返回值、参数、属性的类型不能确定),此时可以使用泛型

泛型就是可以表示某个类型

定义一个泛型

<script lang="ts" setup>
# <T>就是泛型,T是一个泛型的名称(随意起),设置泛型后即可在函数中使用T来表示该类型
function test<T>(name: T): T {
  return name;
}

# 不指名类型,TS会⾃动推断出来
test(10)

# 指名具体的类型
test<number>(10)

</script>

泛型可以写多个

function test<T, K>(a: T, b: K): K{
 return b;
}
// 为多个泛型指定具体⾃值
test<number, string>(10, "hello");

类中使⽤泛型

<script lang="ts" setup>
class MyClass<T> {
  prop: T;
  constructor(prop: T) {
    this.prop = prop;
  }
}

let mm = new MyClass<string>('嘿嘿嘿');
</script>

对泛型的范围进⾏约束

<script lang="ts" setup>
interface Demo {
  length: number;
}
// 泛型T必须是MyInter的⼦类,即:必须拥有length属性
function test<T extends Demo>(arg: T): number {
  return arg.length;
}
test(10); // 类型“number”的参数不能赋给类型“Demo”的参数
test({ name: '张三' }); // 类型“{ name: string; }”的参数不能赋给类型“Demo”的参数
test('123');
test({ name: '张三', length: 10 });
</script>

标签:Typescript,name,age,number,41,面向对象,实例,属性,string
From: https://www.cnblogs.com/songxia/p/18132717

相关文章

  • CF416E 题解
    前置知识:floyd题意给定一个\(n\)个点\(m\)条边的无向简单图,对于每对\((s,t),1\les<t\len\),求出有多少条边被至少一个\(s\tot\)的路径经过。\(n\le500,m\le\frac{n(n-1)}{2}\)题解首先一个很一眼的做法先floyd一遍求出\(dis(i,j)\),接着枚举\((s,......
  • 52 Things: Number 41: Are all side-channels related to power analysis?
    52Things:Number41:Areallside-channelsrelatedtopoweranalysis?52件事:第41件:所有的侧通道都与功率分析有关吗? Thisisthelatestinaseriesofblogpoststoaddressthelistof '52ThingsEveryPhDStudentShouldKnow' todoCryptography:asetof......
  • 42 Typescript编译配置-webpack-babel
    TS编译配置自动编译单个文件tsc1.ts#如果想要自动监视文件的变化,需要添加`-W`配置tsc1.ts-W自动编译整个项目初始化,会自动生成一个tsconfig.json文件,然后直接执行tsc命令,就可以对当前目录的所有ts文件进行编译,生成对应的js文件#初始化项目tsc--init#编译......
  • 20240412打卡
    第七周第一天第二天第三天第四天第五天第六天第七天所花时间5h5h1h6h1h代码量(行)469493155497博客量(篇)11111知识点了解完成了python大作业,花费两天完成音频处理工具完成学习记录app地铁系统json数据转对象地铁查询后端完成蓝桥......
  • TypeScript的严格模式,any和unknown都是顶级类型,any 和 unknown 的区别
    TypeScript中的严格模式在TS的严格模式中;不可以将null,undefined赋值给void;但是在非严格模式中就可以。Tip:在项目中;我们还是要开启严格模式,否则会出现意想不到的错误,我们可以在tsconfig.json文件的compilerOptions的strict中去配置tsconfig.json{"compilerOpti......
  • java面向对象有哪些特征
    Java面向对象编程(OOP)的核心特征通常包括封装性、继承性、多态性和抽象性。具体如下:封装性:封装是指将对象的属性(数据)和行为(方法)绑定在一起,并对对象的实现细节进行隐藏,只暴露出必要的接口给外部使用。这样做的目的是为了保护对象的内部状态,防止外部随意访问和修改。继承性:继承允......
  • 鸿蒙开发TypeScript语言:【TypeScript 安装】
    TypeScript安装本文介绍TypeScript环境的安装。我们需要使用到npm工具安装。NPM安装TypeScript如果你的本地环境已经安装了npm工具,可以使用以下命令来安装。使用国内镜像:npmconfigsetregistryhttps://registry.npmmirror.com安装typescript:npminstall-g......
  • 算法训练营Day08-LeetCode344. 反转字符串 && 541. 反转字符串 II && 151. 反转字符串
    344.反转字符串题目链接:LeetCode344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题思路:字符串首尾字符交换即可完成反转。定......
  • Typescript 详细总结1
    基本数据类型类型注释:numberlet num:number=5//数字类型let str:string='str'//字符串类型let boolen:boolean =true//布尔 类型断言,确定类型后,不能赋其他类型值any类型let  anything:any='ssssss'let  anything:any=223any类型......
  • 算法笔记0411
    1.在C++中,set是一种关联容器,用于存储已排序的键值对,其中每个键都是唯一的。在上面的代码片段中,set<int>s;声明了一个整数类型的set,命名为s,它将自动按照元素值进行排序。set<int>::iteratorit;声明了一个名为it的迭代器,用于遍历set中的元素。迭代器是用于访问容器元素的通用......