【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」

news2024/11/15 21:33:11

TypeScript入坑

    • Interface 接口
      • 简介
      • 接口合并
      • TS 强校验
      • Interface 里支持方法的写入
      • class 类应用接口
      • 接口之间互相继承
      • 接口定义函数
      • interface 与 type 的异同
      • 小案例
    • class 类
      • 类的定义与继承
      • 类的访问类型
      • 构造器 constructor
      • 静态属性,Setter 和 Getter
      • 做个小案例
      • 抽象类
    • Enum 枚举
      • 简介
      • Enum成员的值
      • 同名Enum的合并
      • 数值枚举
      • 字符串枚举
      • 常量枚举
      • keyof 运算符
    • Generics 泛型
      • 简介
      • 类型变量
      • 约束泛型
      • 泛型类
      • 泛型接口
      • 类型参数的约束条件
      • 使用注意点
    • 类型断言
      • 简介
      • 类型断言的条件
      • as const断言
      • 非空断言
      • 断言函数
    • namespace


Interface 接口

🔔
interfacetype 相类似,但不完全一致,type 可以校验基础类型,而 Interface 不支持基础类型的校验。

简介

interface 是对象的模板,可以看作是一种类型约定,中文译为“接口”。使用了某个模板的对象,就拥有了指定的类型结构。

TS 里,能使用 Interface 的话就使用 Interface。

  • 接口只是 TS 帮助我们校验的工具,并不会变成 JS
  • 属性前加上?,代表该变量可有可无
  • 属性前加上 readonly,代表只读不可修改
interface Pereson {
  name: string
  age?: number
  readonly test: string
}
const getPersonName = (person: Pereson) => {
  console.log(person.name)
}

const setPersonName = (person: Pereson, name: string): void => {
  person.name = name
}

const person = {
  name: 'simon',
  age: 18,
  sex: 'male'
}

getPersonName(person)
setPersonName(person, 'lin')

接口合并

多个同名接口会合并成一个接口。

interface Box {
  height: number;
  width: number;
}

interface Box {
  length: number;
}

TS 强校验

如果以字面量的形式传给函数,TS 会进行强校验。例如:

interface Pereson {
  name: string
  age?: number
}
const getPersonName = (person: Pereson) => {
  console.log(person.name)
}

const setPersonName = (person: Pereson, name: string): void => {
  person.name = name
}

const person = {
  name: 'simon',
  age: 18,
  sex: 'male'
}

getPersonName({
  name: 'simon',
  age: 18,
  sex: 'male'
}) // 会报错,sex不在 Person 种
setPersonName(person, 'lin')

// 修改 Interface 解决(最后一行代表的是,可以是任何字符串类型的键,任何值)
interface Pereson {
  name: string
  age?: number
  [propName: string]: any
}

Interface 里支持方法的写入

interface Pereson {
  name: string
  age?: number
  say(): string
}
const person = {
  name: 'simon',
  say() {
    return 'say hello'
  }
}

class 类应用接口

interface Pereson {
  name: string
  age?: number
  say(): string
}
// 语法 implements
class User implements Pereson {
  name = 'simon'
  say() {
    return 'say hello'
  }
}

接口之间互相继承

interface Shape {
  name: string;
}
// 关键字 extends
interface Circle extends Shape {
  radius: number;
}

interface 允许多重继承,可以继承 type 的对象类型,也可以继承 class

接口定义函数

interface SayHi {
  (word: string): string
}
const say: SayHi = (word: string) => {
  return word
}

interface 与 type 的异同

  • type 能够表示非对象类型,而 interface 只能表示对象类型(包括数组、函数等)
  • interface 可以继承其他类型,type 不支持继承(可以通过交叉类型实现继承)
  • 同名 interface 会自动合并,同名 type 则会报错
  • interface 不能包含属性映射(mapping),type 可以
  • this 关键字只能用于 interface
  • type 可以扩展原始数据类型interface 不行
  • interface 无法表达某些复杂类型(比如交叉类型和联合类型)

综上所述,如果有复杂的类型运算,那么没有其他选择只能使用 type
一般情况下,interface 灵活性比较高,便于扩充类型或自动合并,建议优先使用。

小案例

公用属性使用 Interface 进行扩展:

interface Person {
  name: string
}
interface Teacher extends Person {}
interface Student extends Person {
  age: number
}

const teacher = {
  name: 'simon'
}
const student = {
  name: 'jon',
  age: 18
}
const getUserInfo = (user: Person) => {
  console.log(user.name)
}
getUserInfo(teacher) // simon
getUserInfo(student) // jon 

class 类

类的定义与继承

// 类里写属性与方法
class Person {
  name = 'simon'
  getName() {
    return this.name
  }
}
const person = new Person()
console.log(person.getName()) // simon

// 继承类,继承类属于字类,被继承的属于父类
class Teacher extends Person {
  getTeacherName() {
    return 'simon Teacher'
  }
  // 子类可以重写父类的属性与方法
  getName() {
    // super 关键字指向了父类,可以直接调用父类。不会受到类重写的影响
    return super.getName() + 'TTT'
  }
}

const teacher = new Teacher()
console.log(teacher.getName()) // simonTTT
console.log(teacher.getTeacherName()) // simon Teacher

类的访问类型

访回类型:

  • private:允许在类内使用
  • protected:允许在类内及继承的子类中使用
  • public:允许在类的内外调用(默认)

自带方法:

  • readonly:只读属性
  • static:将方法挂载到类上而不是实例上

🔔
直接写在类里的属性或函数,相当于前面加了 public

class Person {
  protected name: string = 'simon'
  private age: number = 10
  public sayHi() {
    console.log('hi' + this.age)
  }
}
class Teacher extends Person {
  public sayBye() {
    return this.name
  }
}
const person = new Person()
person.sayHi()  // hi 10
const teacher = new Teacher()
console.log(teacher.sayBye())  // simon

构造器 constructor

  • constructor 会在 new 实例的时候自动执行

    // 以下两段代码相同, constructor 里, 参数前加上public代表在之前已经声明过这个变量了
    
    // 传统写法
    class Person {
      public name: string
      constructor(name: string) {
        this.name = name
      }
    }
    const person = new Person('simon')
    
    // 简化写法
    class Person {
      // public name: string
      constructor(public name: string) {
        // this.name = name
      }
    }
    const person = new Person('simon')
    console.log(person.name)
    
  • 字类集成父类并使用 constructor 的话,必须先调用父类的 constructor ,并按照父类的参数规则进行

    // super()代表调用父类的 constructor
    // 如果父类没有使用constructor 字类需要调用一个空的super()
    class Person {
      constructor(public name: string) {}
    }
    
    class Teacher extends Person {
      constructor(public age: number) {
        super('zws')
      }
    }
    
    const teacher = new Teacher(28)
    

静态属性,Setter 和 Getter

  • Getter:读
  • Setter:写
// 可以通过getter访问私有属性,通过setter更改私有属性
// 一般用于对数据的加密
class Person {
  constructor(private _name: string) {}
  get name() {
    return this._name + ' has'
  }
  set name(name: string) {
    const realName = name.split(' ')[0]
    this._name = realName
  }
}
const person = new Person('simon')
console.log(person.name) // simon has
person.name = 'simon a has'
console.log(person.name) // simon a has

做个小案例

🙋 通过 TS 创建一个 Demo 类,这个类只能被调用一次

🤔 思路:

  • 不能在外部以 new Demo 的形式创建一个实例(将 constructor 设置为私有属性)
  • 使用 static (将方法挂载到类上而不是实例上)来实现
  • 使用 instance 方法来保存传入的值,并判断
class Demo {
  private constructor(public name: string) {}

  private static instance: Demo
  static getInstance(name: string) {
    if (!this.instance) {
      this.instance = new Demo(name)
    }
    return this.instance
  }
}
const demo1 = Demo.getInstance('simon')
const demo2 = Demo.getInstance('sim')

console.log(demo1.name) // simon
console.log(demo2.name) // simon

抽象类

  • 只能被继承,不能实例化
  • 抽象类里的抽象方法,不能够写具体实现
abstract class Gemo {
  width: number
  getType() {
    return 'Gemo'
  }
  abstract getArea(): number
}
class Cricle extends Gemo {
  // 子类继承了抽象类,里面的抽象方法必须实现一下
  getArea() {
    return 123
  }
}
class Square {}
class Triangle {}

Enum 枚举

简介

实际开发中,经常需要定义一组相关的常量。TypeScript 就设计了 Enum 结构,用来将相关常量放在一个容器里面,方便使用。

你可以使用常量 const 描述某种不会改变的值。但某些值是在一定范围内的一系列常量,如星期(周一~周日)、三原色(红黄蓝)、方位(东南西北)等,这种类型的值称为枚举。

Enum作为类型有一个缺点就是输入任何数值都不报错

Enum成员的值

Enum每个成员的值都可以显式赋值,可以是任意数值,但不能是大整数(Bigint)。

enum Color {
  Red = 90,
  Green = 0.5,
  Blue = 7n, // 报错
}

Enum成员值不能重新赋值,通常我们会在 enum 关键字前加上 const 修饰、加上 const 后,经过编译后Enum成员会被替换为对应的值。

同名Enum的合并

  • 多个同名的 Enum 结构会自动合并。
  • Enum 结构合并时,只允许其中一个的首成员省略初始值,否则报错。
  • 同名 Enum 合并时,不能有同名成员,否则报错。
  • 同名 Enum 合并的另一个限制是,所有定义必须同为 const 枚举或者非 const 枚举,不允许混合使用

数值枚举

使用关键字 enum 来声明一个枚举类型数据。

枚举成员默认为数值类型

enum Direction {
  Up,
  Down,
  Left,
  Right
}

console.log(Direction.Up) // 0
console.log(Direction[0]) // "Up"

未赋初始值的枚举项会接着上个项的值进行递增。

使用 【🔧 tsc工具】 将上述代码编译为 js 后,可以发现 ts 使用 Direction[(Direction["Up"] = 0)] = "Up" 这样的内部实现对对象成员进行了双向的赋值。

由此可以看出,enum 具有双向映射的特点

// ts 代码编译为 js 后
"use strict";
var Direction;
(function (Direction) {
    Direction[Direction["Up"] = 0] = "Up";
    Direction[Direction["Down"] = 1] = "Down";
    Direction[Direction["Left"] = 2] = "Left";
    Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));

console.log(Direction.Up); // 0
console.log(Direction[0]); // "Up"

字符串枚举

枚举成员为字符串时,其之后的成员也必须是字符串。

enum Direction {
  Up, // 未赋值,默认为0
  Down = '南',
  Left = '西',
  Right = '东'
}

🫵 小示例(猜猜结果&原因)

enum Direction {
  Up,
  Down,
  Left = '西',
  Right = '东'
}

console.log(Direction.Left) // "西" 
console.log(Direction[2]) 	// 结果?undefined

🙋 为什么 Direction[1] 打印出来是 undefined 呢?

enum 的工作方式会根据枚举成员是否有显式的值赋予而有所不同。让我们详细分析上面的 Direction 枚举:
枚举成员解释:

  • Up 和 Down:
    • 它们是数字枚举,没有显式赋值,因此会被自动分配递增的数字值:
      • Up 默认值为 0。
      • Down 自动递增为 1。
  • Left 和 Right:
    • 它们是字符串枚举,因为被显式赋值为 ‘西’ 和 ‘东’。

在 TypeScript 中,数字枚举支持反向映射,即你可以通过索引(数字)访问枚举名称。例如,Direction[0] 会返回 "Up"Direction[1] 会返回 "Down"
但是,字符串枚举不支持反向映射。当你在枚举中混合使用数字枚举和字符串枚举时,只有数字枚举支持这种通过数字索引进行反向查找的特性。

🤔 那 为什么 Direction[2]undefined
在你的枚举中,Up0Down1,接下来你定义了 Left = '西'Right = '东'。由于 LeftRight 是字符串枚举成员,不会参与数字递增,因此:

  • 枚举中不存在 Direction[2],所以 Direction[2] 返回 undefined

🏆 解决该问题的关键点:

  • 数字枚举支持反向映射,即可以通过数字查找成员名称。
  • 字符串枚举不支持反向映射,只能通过枚举名来访问值。

常量枚举

你可以使用 constenum 关键字组合,声明一个常量枚举。 常量枚举中不允许使用计算值(变量或表达式)

let a: number = 123;

const enum Direction {
  Up = a, // ✋ 报错:const enum member initializers must be constant expressions.(2474)
  		  // const enum成员初始化器必须是常数表达。
  		  // ⚠️ 报错原因:常量枚举中不允许使用计算值
  		  // 枚举成员为字符串时,其之后的成员也必须是字符串
  Down = '南',
  Left = '西',
  Right = '东'
}

在这里插入图片描述

keyof 运算符

keyof 运算符可以取出 Enum 结构的所有成员名,作为联合类型返回

enum MyEnum {
  A = "a",
  B = "b",
}

// 'A'|'B'
type Foo = keyof typeof MyEnum;

Generics 泛型

在 TypeScript 中,泛型(Generics)是一种在编写代码时不指定具体类型,而是在使用时再确定类型的机制。这使得你可以编写更加通用、灵活且可重用的代码,同时保持类型安全。

泛型的核心思想是参数化类型。通过在函数、类或接口中使用泛型,你可以编写与具体类型无关的代码,而让使用者在调用时提供具体的类型信息。这样一来,你的代码就可以适应多种类型的数据,而不必为每种类型都编写重复的逻辑。

// 定义Map时为接收两个类型参数的函数,在调用时指定类型
const nodePorts = new Map<string, string[]>([
  ['stm', ['stm-entry', 'stm-exit']],
]);

简介

泛型指的是,在定义函数、接口或类的时候不预先指定数据类型,而在使用时再指定类型的特性。

泛型可以提升应用的可重用性,如使用其创建组件,则可以使组件可以支持多种数据类型。

假如需要一个函数,返回传入它的内容 不使用泛型时,它会是这样的:

function echo(arg: any) {
  return arg
}

但这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。于是此时需要一种方法使返回值的类型与传入参数的类型是相同的。

类型变量

这是一种特殊的变量,只用于表示类型而不是值。 使用泛型改写上述函数:

// 类型变量也遵循标识符定义规范,写为T只是习惯上这么做
function echo<T>(arg: T): T {
  return arg
}

这样,传入实参时,会同时将实参的类型传递给类型变量 T,同时返回值也是 T。

场景:交换两个数组元素

不使用泛型会丢失数据类型:

function swap(tuple) {
  return [tuple[1], tuple[0]]
}

使用泛型后,不仅会保有类型推断,还可以直接调用实例的方法:

function swapGeneric<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}

const result2 = swapGeneric(['string', 0.123])

// ts的类型推断系统能够明确得知第一个元素会是数值,而第二个元素会是字符串
result2[0].toFixed(2) // "0.12" 
result2[1].toLocaleUpperCase() // "STRING" 

约束泛型

假设有这样一个场景: 有时想操作某类型的一组值,并且我们知道这组值具有什么样的属性。

下例中,我们想访问 arglength 属性,但是编译器并不能推断每次传入的参数都有 length 属性,于是就报错了。

function echoWithArray<T>(arg: T): T {
  console.log(arg.length) // Error: T doesn't have .length
  return arg
}

经过不充分的考虑后,我们尝试将类型变量指定为数组:

function echoWithArray<T>(arg: T[]): T[] {
  console.log(arg.length)
  return arg
}

此时你也许会发现,这样只能传入数组,不能传入同样具有 length 属性的字符串、类数组对象等。

我们可以定义一个接口来描述约束条件,然后由类型变量继承此接口实现泛型约束:

// 一些编程规范约定接口以大写 I 作为前缀
interface IWithLength {
  length: number
}
function echoWithLength<T extends IWithLength>(arg: T): T {
  console.log(arg.length)
  return arg
}

// 只要包含 length 属性且为数值 均不会报错
const str1 = echoWithLength('str')
const obj = echoWithLength({ length: 10, width: 10 })
const arr2 = echoWithLength([])

泛型类

场景:定义一个类,能实现被 push 入的队列元素与 pop 出的元素的类型一致。

class Queue<T> {
  private data = []
  push(item: T) {
    return this.data.push(item)
  }
  pop(): T {
    return this.data.pop()
  }
}

// 泛型类实例化时要指定具体的类型
const queue = new Queue<number>()
queue.push(1)
queue.push('str') // Error: 类型“string”的参数不能赋给类型“number”的参数。

泛型接口

万能的泛型同样可以用来描述接口:

interface KeyPair<T, U> {
  key: T
  value: U
}

// 泛型接口描述的对象,同样需要满足类型要求
let kp1: KeyPair<number, string> = { key: 123, value: 'str' }
let kp2: KeyPair<string, number> = { key: 'test', value: 123 }

// 描述函数的泛型接口
interface IPlus<T> {
  // 函数应具有两个形参,和一个返回值,它们的类型相同
  (a: T, b: T): T
}

function plus(a: number, b: number): number {
  return a + b
}
function concat(a: string, b: string): string {
  return a + b
}

参数类型不兼容:

在这里插入图片描述

类型参数的约束条件

TypeScript 提供了一种语法,允许在类型参数上面写明约束条件,如果不满足条件,编译时就会报错。这样也可以有良好的语义,对类型参数进行说明。

function comp<T extends { length: number }>(a: T, b: T) {
  if (a.length >= b.length) {
    return a;
  }
  return b;
}

上面实例中,T exitends { length: number } 就是约束条件,表示类型参数T必须满足 { length: number },否则会报错。

comp([1, 2], [1, 2, 3]); // 正确
comp("ab", "abc"); // 正确
comp(1, 2); // 报错

使用注意点

  • 尽量少用泛型。

  • 类型参数越少越好。

  • 类型参数需要出现两次。

    function greet<Str extends string>(s: Str) {
      console.log("Hello, " + s);
    }
    // 等价于
    function greet(s: string) {
      console.log("Hello, " + s);
    }
    
  • 泛型可以嵌套。

    type OrNull<Type> = Type | null;
    
    type OneOrMany<Type> = Type | Type[];
    
    type OneOrManyOrNull<Type> = OrNull<OneOrMany<Type>>;
    

类型断言

简介

对于没有类型声明的值,TypeScript会进行类型推断,很多时候得到的结果,未必是开发者想要的。

type T = "a" | "b" | "c";
let foo = "a";

let bar: T = foo; // 报错

TypeScript 提供了“类型断言”这样一种手段,允许开发者在代码中“断言”某个值的类型,告诉编译器此处的值是什么类型。TypeScript 一旦发现存在类型断言,就不再对该值进行类型推断,而是直接采用断言给出的类型。

type T = "a" | "b" | "c";

let foo = "a";
let bar: T = foo as T; // 正确

类型断言有两种语法。

// 语法一:<类型>值
<Type>value;

// 语法二:值 as 类型
value as Type;

语法一因为跟JSX语法冲突,使用时必须关闭TypeScript的React支持,否则无法识别,由于这个原因,一般使用语法二。

类型断言的条件

类型断言的使用前提是,值的实际类型与断言的类型必须满足一个条件。

expr as T;

上面代码中,expr是实际的值,T是类型断言,它们必须满足下面的条件:exprT的子类型,或者Texpr的子类型。

也就是说,类型断言要求实际的类型与断言的类型兼容,实际类型可以断言为一个更加宽泛的类型(父类型),也可以断言为一个更加精确的类型(子类型),但不能断言为一个完全无关的类型。

as const断言

如果没有声明变量类型,let 命令声明的变量,会被类型推断为 TypeScript 内置的基本类型之一const 命令声明的变量,则被推断为值类型常量

// 类型推断为基本类型 string
let s1 = "JavaScript";

// 类型推断为字符串 “JavaScript”
const s2 = "JavaScript";

非空断言

对于那些可能为空的变量(即可能等于undefinednull),TypeScript 提供了非空断言,保证这些变量不会为空,写法是在变量名后面加上感叹号!

const root = document.getElementById("root")!;

上面示例中,getElementById()方法加上后缀!,表示这个方法肯定返回非空结果。

断言函数

断言函数是一种特殊函数,用于保证函数参数符合某种类型。如果函数参数达不到要求,就会抛出错误,中断程序执行;如果达到要求,就不进行任何操作,让代码按照正常流程运行。

function isString(value) {
  if (typeof value !== "string") throw new Error("Not a string");
}

为了更清晰地表达断言函数,TypeScript 3.7 引入了新的类型写法。

function isString(value: unknown): asserts value is string {
  if (typeof value !== "string") throw new Error("Not a string");
}

assertsis 都是关键词,这里的意思是该函数用来断言参数value的类型是string。


namespace

namespace 是一种将相关代码组织在一起的方式,中文译为“命名空间”。

它出现在 ES 模块诞生之前,作为 TypeScript 自己的模块格式而发明的。但是,自从有了 ES 模块,官方已经不推荐使用 namespace 了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2155202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat中BIO和NIO的区别(Tomcat)

BIO Tomcat中BIO的模型和理论很简单&#xff0c;例图如下 1.Acceptor线程死循环阻塞接收客户端的打过来的socket请求 2.接收到请求之后打包成一个SocketProcessor&#xff08;Runnable&#xff09;&#xff0c;扔到线程池中读取/写入数据 参数配置 1.Acceptor默认线程是1&#…

Day06微信小程序微信登录

微信小程序微信登录 1. 第一&#xff1a;小程序要先发给后端code(只能用一次)&#xff0c; 2. 后端要结合数据发给&#xff08;用get的方式&#xff09; https://api.weixin.qq.com/sns/jscode2session 数据&#xff1a; appidstring小程序的appIdsecretstring小程序的app…

华为为什么要做三折叠屏手机?

前些天我做了一条视频&#xff0c;关于讲华W的新的三折叠屏手机。我说我有点失望&#xff0c;结果引起了华W的同事的一些关注。于是&#xff0c;华W几位高管都跑过来&#xff0c;跟我解释为什么会出现这样的一个状态。 我才知道&#xff0c;这款手机他们其实是亏着钱在卖的。因…

【大模型实战篇】关于Bert的一些实操回顾以及clip-as-service的介绍

最近在整理之前的一些实践工作&#xff0c;一方面是为了笔记记录&#xff0c;另一方面也是自己做一些温故知新&#xff0c;或许对于理解一些现在大模型工作也有助益。 1. 基于bert模型实现中文语句的embedding编码 首先是基于bert模型实现中文语句的embedding编码&#xff0c;…

使用库函数点亮一个LED灯

软件设计 STM32Gpio的介绍 如果想让LED0点亮&#xff0c;那么R12就要是高电平&#xff0c;LED0就要是低电平&#xff0c;也就是PF9就是低电平 F407系统主频要工作在168MHZ F103的话是工作在72mhz F429的话就180MHZ 接着我们就要使能Gpio的时钟&#xff0c;使能之后对GPIO相关…

ES7 -- ES13

1. ES7 – 2016 1. 数组的includes方法 数组中是否包含某个元素&#xff0c;返回值为boolean let arr [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; arr.includes(5); // true2. ** 幂次方 let res 2 ** 3; // 82. ES8 --2017 1. 字符串补全 基本使用 let str 123;str.padStart…

Django 请求配置

http请求配置 请求流程 urls.py配置 from first_app import viewsurlpatterns [path(admin/, admin.site.urls),path(test/,views.first_test), ] views.py配置 from django.shortcuts import render,HttpResponse# Create your views here. def first_test(request):prin…

Kubernetes 安装网络插件flannel报错Init:ImagePullBackOff,flannel下载镜像报错问题解决

Kubernetes1.28安装网络插件flannel&#xff0c;报错Init:ImagePullBackOff &#xff0c;flannel安装下载镜像失败 问题 1.安装flannel kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml 2.flannel报错信息 执行查看安装…

Flutter 约束布局

配置插件依赖 设置组件大小 通过属性 childConstraints 实现 分别设置 约束布局一 和 约束布局二 大大小为:160 和 200 点击查看代码文件 class SummaryPageState extends State<SummaryPage1> {ConstraintId constraintId_1 = ConstraintId(ConstraintId_1);Constrain…

【GUI设计】基于Matlab的图像处理GUI系统(1),用matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于Matlab的图像处理GUI系统&#xff0c;用matlab实现。 本次内容主要分为两部分&a…

专题七_分治_快排_归并_算法专题详细总结

目录 分治 一、分治思想的概念 二、分治思想的步骤 1. 颜⾊分类&#xff08;medium&#xff09; 解析&#xff1a; 2. 快速排序&#xff08;medium&#xff09; 解析&#xff1a; 总结&#xff1a; 3. 快速选择算法&#xff08;medium&#xff09; 解析&#xff1a; …

【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9&#xff09; 实验一 Lab: Reflected XSS into HTML context with nothing…

maven手动导入本地仓库

maven手动导入本地仓库 1.在maven仓库下载对应的依赖 一定要把jar包下载到maven仓库的bin下 2.找到自己仓库的maven仓库下的bin目录cmd进去 在cmd窗口中输入以下命令&#xff1a;&#xff08;这里根据你的groupId、artifactId、version修改即可&#xff09; <!-- https:…

乱弹篇(53)丹桂未飘香

今天是2024年“秋分”节气&#xff0c;也是第7个中国“农民丰收节”&#xff0c;本“人民体验官”推广人民日报官方微博文化产品《文化中国行看丰收之美》。 截图&#xff1a;来源“人民体验官”推广平台 人民微博说&#xff1a;“春华秋实&#xff0c;岁物丰成。”又说&#…

dhtmlxGantt 甘特图 一行展示多条任务类型

效果如图: 后台拿到数据 处理之后如图: 含义: 如上图所示, 如果一行需要展示多个 需要给父数据的那条添加render:split属性, 子数据的parent为父数据的Id即可 切记 父数据的id 别为0 为0 时 会出现错乱 因为有些小伙伴提出分段展示的数据结构还是有点问题,下面展示一个完整…

机器人时代的“触觉革命”:一块小传感器如何颠覆你的认知?

你是否曾经想过,机器人也能像人类一样有“触觉”?不再是简单的机械操作,而是具备真正的感知能力,能够学会精细的任务。今天我想和你聊聊一种让机器人“长出触觉”的技术:一种小巧的触觉传感器,它的名字叫“AnySkin”。别看它小,它的潜力可一点都不小,或许能彻底改变我们…

Windows下如何定时执行自定义任务

目录 一.前言二.设置定时自动执行自定义任务 一.前言 本文环境是Windows11系统。 有时候我们希望能够在Windows下定时自动执行自定义任务&#xff0c;比如检测数据库服务的状态。那在Windows下怎么定时自动执行自定义任务&#xff0c;这篇文章介绍一种方法。 二.设置定时自动…

NLP 主流应用方向

主流应用 文本分类文本匹配序列标注生成式任务 应用细分 文本纠错话者分离 本质为文本分类任务数字归一化 实现数字映射&#xff0c;提高内容可读性 如将一九九九转1999

AI基础 L26 Introduction to Automated Planning - II

ADL Action Description Language (ADL) is a richer language than STRIPS. It allows for • Positive and negative literals in states • The open world assumption • Quantified variables in goals as well as conjunctions and disjunctions • Conditional effects …

Web_php_include 攻防世界

<?php show_source(__FILE__); echo $_GET[hello]; $page$_GET[page]; while (strstr($page, "php://")) { 以是否检测到php://为判断执行循环$pagestr_replace("php://", "", $page);//传入空值&#xff0c;替换 } include($page); ?&g…