【HarmonyOS NEXT】ArkTs函数、类、接口、泛型、装饰器解析与使用
1. 前置学习文档
- 【HarmonyOS NEXT】ArkTs数据类型解析与使用(https://juejin.cn/spost/7448894500348608522)
2. 前言
在原生JavaScript中只有函数和类的实现,为了更好的面向对象编程,TypeScript 引入了接口、泛型、装饰器等特性。ArkTS也继承了这些特性。
3.函数
3.1 函数声明
函数声明引入一个函数,包含其名称、参数列表、返回类型和函数体。
以下示例是一个简单的函数,包含两个string类型的参数,返回类型为string:
function add(x: string, y: string): string {let z: string = `${x} ${y}`;return z;
}
//另外一种写法,如果能推断出返回类型,可以省略返回类型【但是不建议这么做,转眼间你就看不出返回类型】
function add(x: string, y: string) {let z: string = `${x} ${y}`;return z;
}
3.2 可选参数
可选参数的格式可为name?: Type。翻译成人话就是:可以不传或者传该参数
function hello(name?: string) {if (name == undefined) {console.log('Hello!');} else {console.log(`Hello, ${name}!`);}
}
可选参数的另一种形式为设置的参数默认值。如果在函数调用中这个参数被省略了,则会使用此参数的默认值作为实参。
function multiply(n: number, coeff: number = 2): number {return n * coeff;
}
multiply(2); // 返回2*2
multiply(2, 3); // 返回2*3
3.3 Rest参数[剩余参数]
函数的最后一个参数可以是rest参数。使用rest参数时,允许函数或方法接受任意数量的实参。类似于Kotlin中的可变参数 vararg。
rest参数是ES6新增的特性,rest参数的形式为:…变量名:类型[];扩展运算符是三个点(…)
function sum(...numbers: number[]): number {let res = 0;for (let n of numbers)res += n;return res;
}sum() // 返回0
sum(1, 2, 3) // 返回6
3.4 函数类型
函数类型指的是,可以使用Aliases类型 关键字 type 来声明指定的函数类型,Kotlin 也有类似的特性,typealias
简单来说,就是可以把一个函数当做参数传递。
type trigFunc = (x: number) => number // 这是一个函数类型function do_action(f: trigFunc,args:number):number {return f(args);//调用函数
}function add(x: number): number {return x + 10086
}function sub(x: number): number {return x - 10086
}console.log(do_action(add,100).toString())//输出10186
console.log(do_action(sub,100).toString())//-9986
3.5 箭头函数或Lambda函数
函数可以定义为箭头函数,例如:
//转箭头函数之间
let sum = function (x: number, y: number): number {return x + y;
}
//转箭头函数之后
let sum = (x: number, y: number): number => {return x + y;
}
箭头函数的返回类型可以省略;省略时,返回类型通过函数体推断。
表达式可以指定为箭头函数,使表达更简短,因此以下两种表达方式是等价的:
let sum1 = (x: number, y: number) => { return x + y; }
let sum2 = (x: number, y: number) => x + y
3.6 闭包
箭头函数通常在另一个函数中定义。作为内部函数,它可以访问外部函数中定义的所有变量和函数。
为了捕获上下文,内部函数将其环境组合成闭包,以允许内部函数在自身环境之外的访问。
闭包属于JS中比较特殊的内容,在ArkTS中和TS/JS也有一定出入,这里后期专门出一篇文档来说明优缺点和使用场景。
//这个示例中,箭头函数闭包捕获count变量。
function f(): () => number {let count = 0;return (): number => { count++; return count; }
}let z = f();
z(); // 返回:1
z(); // 返回:2//闭包实例代码
function fn1() {let a = 1;function fn2() {a++;console.log(a);}return fn2;
}
const fn2 = fn1();
//闭包函数执行完后外部作用域变量仍然存在,并保持状态
fn2() //2
fn2() //3
3.7 函数重载
通过Union类型 声明,即可实现函数中一个属性,支持多种类型
function foo(x: number): void; /* 第一个函数定义 */
function foo(x: string): void; /* 第二个函数定义 */
function foo(x: number | string): void { /* 函数实现 */
}foo(123); // OK,使用第一个定义
foo('aa'); // OK,使用第二个定义
4. 类
ES5之前不存在类的概念,为了使JavaScript更像面向对象,ES6版本引入class概念,但其本质是基于函数去实现的,感兴趣的可以看下面的几篇文章:
- JavaScript ES6中 class的本质
- javascript 类的本质
4.1 声明和使用
在以下示例中,定义了Person类,该类具有字段name和surname、构造函数和方法fullName:
class Person {name: string = ''surname: string = ''constructor (n: string, sn: string) {this.name = n;this.surname = sn;}fullName(): string {return this.name + ' ' + this.surname;}
}
//定义类后,可以使用关键字new创建实例:
let p = new Person('John', 'Smith');
console.log(p.fullName());//或者,可以使用对象字面量创建实例:
class Point {x: number = 0y: number = 0
}
let p: Point = {x: 42, y: 42};
//
4.2 构造函数
constructor方法是一个特殊的方法,这种方法用于创建和初始化一个由class创建的对象。一个类只能拥有一个名为“constructor”的特殊方法【JS中的Class 本质是基于函数去实现的】。因为只能拥有一个class 构造函数,所以在ArkTS中,没有向Java类的重载。
如果不指定一个构造函数 (constructor) 方法,则使用一个默认的构造函数 (constructor)
//构造函数定义如下:
constructor ([parameters]) {// ...
}//如果未定义构造函数,则会自动创建具有空参数列表的默认构造函数,例如:
class Point {x: number = 0y: number = 0
}
let p = new Point();
4.3 通过联合类型实现重载
// 声明
function test(param: User): number;
function test(param: number, flag: boolean): number;
// 实现
function test(param: User | number, flag?: boolean) {if (typeof param === 'number') {return param + (flag ? 1 : 0)} else {return param.age}
}
4.4 静态字段
使用关键字static将字段声明为静态。静态字段属于类本身,类的所有实例共享一个静态字段。
要访问静态字段,需要使用类名:
class Person {static numberOfPersons = 0constructor() {// ...Person.numberOfPersons++;// ...}
}
Person.numberOfPersons;
4.5 字段初始化[必看]
为了减少运行时的错误和获得更好的执行性能,
ArkTS要求所有字段在声明时或者构造函数中显式初始化。这和标准TS中的strictPropertyInitialization模式一样。
以下代码是在ArkTS中不合法的代码。
class Person {name: string // undefinedsetName(n:string): void {this.name = n;}getName(): string {// 开发者使用"string"作为返回类型,这隐藏了name可能为"undefined"的事实。// 更合适的做法是将返回类型标注为"string | undefined",以告诉开发者这个API所有可能的返回值。return this.name;}
}let jack = new Person();
// 假设代码中没有对name赋值,例如调用"jack.setName('Jack')"
jack.getName().length; // 运行时异常:name is undefined
在ArkTS中,应该这样写代码。
class Person {name: string = ''setName(n:string): void {this.name = n;}// 类型为'string',不可能为"null"或者"undefined"getName(): string {return this.name;}
}
如果你非要声明一个没有初始值的字段,那么可以这样写
class Person {name?: string = ''setName(n: string): void {this.name = n;}getName(): string {return this.name ?? ""; //注意这里,因为name 未赋值,则是undefined类型,为了保证控安全,使用了空值合并运算符 ?? 来保证一定有值}
}
4.6 getter和setter【存取器(Accessors)】
setter和getter可用于提供对对象属性的受控访问。这里的get set方法和kotlin中的类似
class Person {name: string = ''private _age: number = 0get age(): number { return this._age; }set age(x: number) {if (x < 0) {throw Error('Invalid age argument');}this._age = x;}
}let p = new Person();
p.age; // 输出0
p.age = -42; // 设置无效age值会抛出错误
4.7 可见性修饰符
类的方法和属性都可以使用可见性修饰符。
可见性修饰符包括:private、protected和public。默认可见性为public。
- Public(公有)
public修饰的类成员(字段、方法、构造函数)在程序的任何可访问该类的地方都是可见的。 - Private(私有)
private修饰的成员不能在声明该成员的类之外访问,例如:
class C {public x: string = ''private y: string = ''set_y (new_y: string) {this.y = new_y; // OK,因为y在类本身中可以访问}
}
let c = new C();
c.x = 'a'; // OK,该字段是公有的
c.y = 'b'; // 编译时错误:'y'不可见
- Protected(受保护)
protected修饰符的作用与private修饰符非常相似,不同点是protected修饰的成员允许在【子类/派生类】中访问,例如:
class Base {protected x: string = ''private y: string = ''
}
class Derived extends Base {foo() {this.x = 'a'; // OK,访问受保护成员this.y = 'b'; // 编译时错误,'y'不可见,因为它是私有的}
}
- readonly修饰符
你可以使用 readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。 熟悉kotlin 的会发现这个特性特别像 kotlin class 中的 val 修饰符
ArkTS
class Dog {public readonly name: String;public constructor(name: string) {this.name = name;}
}let dog = new Dog("旺财")
dog.name = "狗蛋" //不允许修改
Kotlin
class Dog(val name: String)val dog = Dog("旺财")
dog.name="狗蛋" //不允许修改
4.8 对象字面量
对象字面量是一个表达式,可用于创建类实例并提供一些初始值。它在某些情况下更方便,可以用来代替new表达式。
对象字面量的表示方式是:封闭在花括号对({})中的’属性名:值’的列表。
class C {n: number = 0s: string = ''
}let c: C = {n: 42, s: 'foo'};
ArkTS是静态类型语言,如上述示例所示,对象字面量只能在可以推导出该字面量类型的上下文中使用。其他正确的例子:
class C {n: number = 0s: string = ''
}function foo(c: C) {}let c: Cc = {n: 42, s: 'foo'}; // 使用变量的类型
foo({n: 42, s: 'foo'}); // 使用参数的类型function bar(): C {return {n: 42, s: 'foo'}; // 可以推导出来,所以可以直接使用返回类型
}
也可以在数组元素类型或类字段类型中使用:
class C {n: number = 0s: string = ''
}
let cc: C[] = [{n: 1, s: 'a'}, {n: 2, s: 'b'}];
4.9 继承
一个类可以继承另一个类(称为基类)
继承类继承基类的字段和方法,但不继承构造函数。继承类可以新增定义字段和方法,也可以覆盖其基类定义的方法。
基类也称为“父类”或“超类”。继承类也称为“派生类”或“子类”。
class [extends BaseClassName] {// ...
}
class Animal {constructor(name) {this.name = name;}sayHi() {return `我的名字是 ${this.name}`;}
}class Cat extends Animal {constructor(name) {super(name); // 调用父类的 constructor(name)console.log(this.name);}sayHi() {return '你好, ' + super.sayHi(); // 调用父类的 sayHi()}
}let a = new Animal('张三');
console.log(a.sayHi()); // 我的名字是张三let c = new Cat('李四');
console.log(c.sayHi()); // 你好, 我的名字是李四
4.10 抽象类
abstract
用于定义抽象类和其中的抽象方法。
什么是抽象类?
- 抽象类是不允许被实例化的
- 抽象类中的抽象方法必须被子类实现
abstract class Animal {public name;public constructor(name) {this.name = name;}public abstract sayHi();
}class Cat extends Animal {public sayHi() {console.log(`Meow, My name is ${this.name}`);}
}
let a = new Animal('张三');//这种不可以,因为抽象类不能被实例化let cat = new Cat('Tom');
5. 接口
接口声明引入新类型。接口是定义代码协定的常见方式。
任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。
接口通常包含属性和方法的声明
// 接口:
interface AreaSize {color: string, // 属性的声明calculateAreaSize(): number // 方法的声明someMethod(): void; // 方法的声明
}// 实现:
class RectangleSize implements AreaSize {color: string;width: numberheight: numberconstructor(color: string, width: number, height: number) {this.color = colorthis.width = widththis.height = height}someMethod(): void {console.log('计算面积之前得方法');}calculateAreaSize(): number {this.someMethod();return this.width * this.height;}
}
5.1 接口属性
接口属性可以是字段、getter、setter或getter和setter组合的形式。
属性字段只是getter/setter对的便捷写法。以下表达方式是等价的:
interface Style {color: string
}interface Style {get color(): stringset color(x: string)
}
实现接口的类也可以使用以下两种方式:
interface Style {color: string
}class StyledRectangle implements Style {color: string = ''
}interface Style {color: string
}class StyledRectangle implements Style {private _color: string = ''get color(): string { //获取颜色之前可以做一些处理return this._color;}set color(x: string) {//设置颜色之前可以做一些校验this._color = x;}
}
5.2 接口继承
接口可以继承其他接口,继承接口包含被继承接口的所有属性和方法,还可以添加自己的属性和方法,如下面的示例所示:
interface Style {color: string
}interface ExtendedStyle extends Style {width: number
}class Cat implements ExtendedStyle {width: number;color: string;constructor(width: number, color: string) {this.width = widththis.color = color}
}
6. 泛型
如果需要创建可重用的组件,一个组件可以支持多种类型的数据。此时就可以用到泛型来实现。
设计泛型的关键目的是在成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值。
6.1 使用
//下面是一个创建指定长度和指定类型数组的方法
function createArray<T>(length: number, value: T): Array<T> {let result: T[] = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;
}createArray<string>(3, 'x'); // 输出长度为3,内容都是X的数组,['x', 'x', 'x']
createArray<number>(3, 1); // 输出长度为3,内容都是1的数组,[1, 1, 1]
6.2 泛型约束
我们有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在下面 printLength
例子中,我们想访问arg
的length
属性,但是编译器并不能证明每种类型都有length
属性,所以就报错了。
这个特性类似Kotlin 泛型中的型变特性 ,即只可以消费而不可以生产
function printLength<T>(arg: T): T {console.log(arg.length); // Error: T doesn't have .lengthreturn arg;
}
此时泛型约束就派上了用场,我们定义一个接口来描述约束条件。 创建一个包含 .length
属性的接口,使用这个接口和extends
关键字来实现约束:
interface LengthInterface {length: number;
}function loggingIdentity<T extends LengthInterface>(arg: T): T {console.log(arg.length+"");return arg;
}loggingIdentity<string>("小猪佩奇身上纹")//日志打印 7【因为string 】
6.3 泛型默认值
泛型类型的类型参数可以设置默认值。这样可以不指定实际的类型实参,而只使用泛型类型名称。
当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用
interface A<T=string> {name: T;
}const strA: A = { name: 123 };//报错,因为没有指定泛型类型,泛型默认是string类型,但是创建的泛型是数字类型
const numB: A<number> = { name: 101 };//正确,因为指定了类型,所以可用
7. 装饰器
- 随着TypeScript和ES6里引入了类,在一些场景下我们需要额外的特性来支持标注或修改类及其成员。 装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。
- 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用
@expression
这种形式,expression
求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。- 在ArkTS中 常见的状态管理其实就是一种装饰器
7.1 装饰器的分类
- 类装饰器(Class decorators)
- 属性装饰器(Property decorators)
- 方法装饰器(Method decorators)
- 参数装饰器(Parameter decorators)
7.2 类装饰器
declare type ClassDecorator = <TFunction extends Function>(target: TFunction
) => TFunction | void;
类装饰器顾名思义,就是用来装饰类的。它接收一个参数:
- target: TFunction - 被装饰的类
7.3 属性装饰器
属性装饰器声明:
declare type PropertyDecorator = (target:Object, propertyKey: string | symbol ) => void;
属性装饰器顾名思义,用来装饰类的属性。它接收两个参数:
- target: Object - 被装饰的类
- propertyKey: string | symbol - 被装饰类的属性名
7.4 方法装饰器
方法装饰器声明:
declare type MethodDecorator = <T>(target:Object, propertyKey: string | symbol, descriptor: TypePropertyDescript<T>) => TypedPropertyDescriptor<T> | void;
方法装饰器顾名思义,用来装饰类的方法。它接收三个参数:
- target: Object - 被装饰的类
- propertyKey: string | symbol - 方法名
- descriptor: TypePropertyDescript - 属性描述符
7.5 参数装饰器
参数装饰器声明:
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number ) => void
参数装饰器顾名思义,是用来装饰函数参数,它接收三个参数:
- target: Object - 被装饰的类
- propertyKey: string | symbol - 方法名
- parameterIndex: number - 方法中参数的索引值
7.6 综合例子
7.6.1 新建装饰器
新建一个GlobalDecorators.ets 的文件用于存放自定义装饰器的方法
/*** @param target: TFunction - 被装饰的类*/
export function 类装饰器(target: Object) {console.log("我是类装饰器:target:" + target)
}/*** @param target - 被装饰的类* @param key 被装饰类的属性名*/
export function 属性装饰器(target: Object, key: string) {console.log("我是属性装饰器:target:" + target + "__key:" + key)
}/*** @param target: Object - 被装饰的类* @param propertyKey: string - 方法名* @param descriptor: PropertyDescriptor - 属性描述符*/
export function 方法装饰器(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {console.log("我是方法装饰器:target:" + target + "__propertyKey:" + propertyKey + "__descriptor:" + descriptor)
}/*** @param target: Object - 被装饰的类* @param propertyKey: string - 方法名* @param parameterIndex: number - 方法中参数的索引值*/
export function 参数装饰器(target: Object, propertyKey: string, parameterIndex: number) {console.log("我是参数装饰器:target:" + target + "__propertyKey:" + propertyKey + "__parameterIndex:" + parameterIndex)
}
7.6.2 使用装饰器
import { Person, 类装饰器, 属性装饰器, 方法装饰器 } from '../GlobalDecorators';@类装饰器
export class Person {@属性装饰器public name: string = ""@方法装饰器dog(@参数装饰器 str: string) {console.log(str)}
}
7.7 ArkTs装饰器和Java注解的区别
特性 | ArkTs 装饰器 | Java 注解 |
---|---|---|
设计目的 | 用于修改类的结构和行为 | 提供元数据信息,不直接影响行为 |
运行时行为 | 可以直接影响对象的行为,因为它们是函数 | 不直接影响行为,需要通过反射等机制来处理 |
实现机制 | 作为运行时执行的函数 | 作为元数据标记,可选地通过注解处理器在编译时处理 |
使用场景 | 类、方法、属性、参数、访问器的装饰 | 类、方法、字段、参数等的元数据描述 |
参数 | 可以接受参数 | 可以接受参数,通常作为配置选项 |
反射 | TypeScript不直接支持反射,但可以通过JavaScript特性来实现 | Java支持反射,可在运行时查询注解信息 |
编译时代码分析 | 不适用 | 可以通过注解处理器进行代码生成等编译时分析 |
框架应用 | Angular等框架中用于定义组件、服务等,ArkUI中各种状态管理 | Spring、Arouter等框架中用于配置和逻辑处理 |
相关文章:
【HarmonyOS NEXT】ArkTs函数、类、接口、泛型、装饰器解析与使用
1. 前置学习文档 【HarmonyOS NEXT】ArkTs数据类型解析与使用(https://juejin.cn/spost/7448894500348608522) 2. 前言 在原生JavaScript中只有函数和类的实现,为了更好的面向对象编程,TypeScript 引入了接口、泛型、装饰器等特性。ArkTS也继承了这些特性…...
【数学】矩阵的逆与伪逆 EEGLAB
文章目录 前言matlab代码作用EEGLAB 中的代码总结参考文献 前言 在 EEGLAB 的使用中,运行程序时出现了矩阵接近奇异值,或者缩放错误。结果可能不准确。RCOND 1.873732e-20 的 bug,调查 EEGLAB 后发现是 raw 数据的问题。 matlab代码 A_1 …...
用github镜像加速, --recursive还是去github站怎么处理?
小伙伴们大多碰到过github抽风的情况,时通时断,时快时慢,非常考验心情。 以前碰到连不上的时候,我大多就是在gitee和gitcode网站找一下镜像,找到后直接git clone 新地址即可。但是碰到 --recursive的时候就不行了&…...
第P2周:Pytorch实现CIFAR10彩色图片识别
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标 实现CIFAR-10的彩色图片识别实现比P1周更复杂一点的CNN网络 具体实现 (一)环境 语言环境:Python 3.10 编 译 器: …...
springboot3访问第三方接口
添加依赖(如果尚未添加) 在pom.xml文件中,确保已经包含spring-boot-starter-web依赖,因为RestTemplate通常在这个依赖范围内。如果没有,添加如下依赖: <dependency><groupId>org.springframe…...
Ubuntu K8s
https://serious-lose.notion.site/Ubuntu-K8s-d8d6a978ad784c1baa2fc8c531fbce68?pvs74 2 核 2G Ubuntu 20.4 IP 172.24.53.10 kubeadmkubeletkubectl版本1.23.01.23.01.23.0 kubeadm、kubelet 和 kubectl 是 Kubernetes 生态系统中的三个重要组件 kubeadm: 主…...
大数据第三次周赛
类斐波那契循环数 #include<bits/stdc.h> using namespace std; #define int long long int arr[1000010]; bool key(int k){int num0;string strto_string(k);for(int i0;i<str.length();i){arr[num]str[i]-0;}int l0,rnum-1;int shix0; while(shix<k){shix0;for…...
《Java核心技术I》Swing用户界面组件
Swing和模型-视图-控制器设计模式 用户界面组件各个组成部分,如按钮,复选框,文本框或复杂的树控件,每个组件都有三个特征: 内容,如按钮的状态,文本域中的文本。外观,颜色,…...
Web开发 -前端部分-CSS
CSS CSS(Cascading Style Sheet):层叠样式表,用于控制页面的样式(表现)。 一 基础知识 1 标题格式 标题格式一: 行内样式 <!DOCTYPE html> <html lang"en"><head><meta…...
旅游系统旅游小程序PHP+Uniapp
旅游门票预订系统,支持景点门票、导游产品便捷预订、美食打卡、景点分享、旅游笔记分享等综合系统 更新日志 V1.3.0 1、修复富文本标签 2、新增景点入驻【高级版本】3、新增门票核销【高级版】4、新增门票端口【高级版】...
Windows 与 Linux 下 Ping IPv6 地址 | 常用网络命令
注:本文为网络命令相关文章合辑。 未整理去重。 一、IPv6 概述 IPv6 即 “Internet 协议版本 6”,因 IPv4 地址资源面临耗尽问题而被引入以替代 IPv4。IPv6 则提供了理论上多达 2 128 2^{128} 2128 个地址,有效解决地址不足困境。 IPv6 具…...
前端学习一
一 进程与线程 线程是进程执行的最小单位,进程是系统分配任务的最小单位。 一个进程可执行最少一个线程。线程分为子线程和主线程。 主线程关闭则子线程关闭。 二 浏览器进程 浏览器是多进程多线程应用。 进程包括: 浏览器进程 负责程序交互渲染…...
【Python · PyTorch】卷积神经网络(基础概念)
【Python PyTorch】卷积神经网络 CNN(基础概念) 0. 生物学相似性1. 概念1.1 定义1.2 优势1.2.1 权重共享1.2.2 局部连接1.2.3 层次结构 1.3 结构1.4 数据预处理1.4.1 标签编码① One-Hot编码 / 独热编码② Word Embedding / 词嵌入 1.4.2 归一化① Min-…...
Spring Framework 路径遍历漏洞复现(CVE-2024-38819)
hu0x01 产品描述: Spring Framework 是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。它结合了轻量级的容器和依赖注入功能,提供了一种使用 POJO 进行容器配置和面向切面的编程的简单方法,以及一组用于AOP的模块。0x02 漏洞描述: Spring Framework 存…...
心法利器[122] | 算法面试的八股和非八股讨论
心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 2023年新的文章合集已经发布,获取方式看这里:又添十万字-CS的陋室2023年文章合集来袭,更…...
实操给自助触摸一体机接入大模型语音交互
本文以CSK6 大模型开发板串口触摸屏为例,实操讲解触摸一体机怎样快速增加大模型语音交互功能,使用户能够通过语音在一体机上查询信息、获取智能回答及实现更多互动功能等。 在本文方案中通过CSK6大模型语音开发板采集用户语音,将语音数据传输…...
AJAX家政系统自营+多商家家政系统服务小程序PHP+Uniapp
一款同城预约、上门服务、到店核销家政系统,用户端、服务端、门店端各端相互依赖又相互独立,支持选择项目、选择服务人员、选择门店多种下单方式,支持上门服务和到店核销两种服务方式,支持自营和多商家联营两种运营模式࿰…...
LiveData源码研究
LiveData 源码分析 前言 用过MVVM的大概知道LiveData可以感知组件的生命周期,当页面活跃时,更新页面数据, 当页面处于非活跃状态,它又会暂停更新,还能自动注册和注销观测者,能有效避免内存泄漏和不必要的…...
Root软件学习
一、命令行输入下方命令打开root文件 root filename.root 二、在root命令行下输入.help查看root下可用的指令 .help输入.q是退出root命令行 .q 三、输入下方指令查看当前打开的root文件的目录 .ls 四、打印Hits树下的内容(print) 方框里是各种树文…...
研发文档管理系统:国内外9大选择比较
文章主要对比了9款国内外研发文档管理系统:1.PingCode; 2. Worktile; 3. 飞书; 4. 石墨文档; 5. 腾讯文档; 6. 蓝湖; 7. Confluence; 8. Notion; 9. Slab。 在企业研发过…...
centos 7.9 freeswitch1.10.9环境搭建
亲测版本centos 7.9系统–》 freeswitch1.10.9 一、下载插件 yum install -y git alsa-lib-devel autoconf automake bison broadvoice-devel bzip2 curl-devel libdb4-devel e2fsprogs-devel erlang flite-devel g722_1-devel gcc-c++ gdbm-devel gnutls-devel ilbc2...
嵌入式驱动开发详解17(CAN驱动开发)
文章目录 前言CAN简介CAN收发器CAN协议讲解电气特性传输协议数据帧遥控帧错误帧过载帧帧间隔 同步矫正 CAN控制器CAN控制器模式CAN接收器CAN波特率 CAN设备树分析CAN测试后续参考文献 前言 该专栏主要是讲解嵌入式相关的驱动开发,但是由于部分模块的驱动框架过于复…...
探索 Janus-1.3B:一个统一的 Any-to-Any 多模态理解与生成模型
随着多模态技术的不断发展,越来越多的模型被提出以解决跨文本与图像等多种数据类型的任务。Janus-1.3B 是由 DeepSeek 推出的一个革命性的模型,它通过解耦视觉编码并采用统一的 Transformer 架构,带来了一个高度灵活的 any-to-any 多模态框架…...
黑马头条day01 微服务搭建
1.请求调用流程 如http://localhost:8803/static/js/2.0195d7180dc783c3fe99.js这种静态资源,采用http的发送到本地8803端口的静态资源请求,而nginx配置的监听8801、8802、8803,所以请求走到nginx,nginx的admin配置文件 upstream…...
AI辅助编程工具对比:Cursor AI、Windsurf AI 和 GitHub Copilot
功能和特性 1. Cursor AI 基于VS Code构建,集成了GPT-4等多个AI模型,提供高级智能支持。支持AI代码补全、错误修正以及通过自然语言执行命令。具备多文件编辑和上下文理解能力,能够在复杂项目中提供跨文件的智能建议。提供标签功能…...
【Qt】qt安装
在工作一年之后,还是想做一个Qt的教程,遥想研一刚刚接触Qt,从0到1学习,没有什么参考书籍,网上的资料也不多,幸好Qt官方文档写得好,加上自己肯研究,才堪堪入门。 现在我想自己写一个…...
课设项目十:智能手电筒(使用金沙滩51单片机)
00 题目介绍 功能: 硬件设置: 使用51单片机连接光敏传感器、LED灯和手电筒开关按钮。 环境感知: 实时监测周围光照强度。 LED控制: 根据光照强度自动控制LED灯的开关。 手动控制: 提供手电筒开关按钮,…...
Oracle中COUNT函数对NULL和空字符串的处理方式
Oracle中,使用COUNT函数的时候,COUNT()和COUNT(null)得到的结果都是0,也就是说,如果我们COUNT中选择的那列属性中为null的或者的那行是不会被计数的。MySQL中count(null)效果和Oracle中一样,但是count()能正常计数。 在…...
OpenHarmony和OpenVela的技术创新以及两者对比
两款有名的国内开源操作系统,OpenHarmony,OpenVela都非常的优秀。本文对二者的创新进行一个简要的介绍和对比。 一、OpenHarmony OpenHarmony具有诸多有特点的技术突破和重要贡献,以下是一些主要方面: 架构设计创新 分层架构…...
Windows常用命令
该篇文章是博主不断从工作中总结而来,会持续不断更新 文件和目录管理命令 列出指定目录中的文件和子目录:dir 路径 更改当前工作目录:cd 路径 创建新目录:mkdir 目录名 删除空目录:rmdir 目录名 删除指定文件…...
牛客网 SQL2查询多列
SQL2查询多列 select device_id,gender,age,university //查询哪些字段 from user_profile //从哪个表中查找 每日问题 C 中面向对象编程如何处理异常? 在C中,面向对象编程(OOP)处理异常主要通过异常处理机制来实现。C 提供了…...
容器,网络基础
小结: 1、利用网桥和虚拟网卡 2、利用Veth Pair虚拟设备,一个网卡可以直接出现在另外一个网卡中 一个Linux容器能看见的“网络栈”,实际上是被隔离在它自己的Network Namespace当中的 “网络栈”,就包括了:网卡&#…...
Treap树堆【东北大学oj数据结构8-4】C++
题面 二叉搜索树会因为插入的数据的值可能变得不平衡,搜索/插入/删除操作的效率变得低效。例如,如果依次插入 n 个升序的数据,则树将看起来像一个列表,其高度将为 n,并且查询时间变得很长。一个解决策略是随意打乱要插…...
基于STM32的智电表系统课题设计思路:python友好界面、ADC、UART串口、数据分析
1. 项目选题与需求分析 1.1 选题背景和动机 随着社会的快速发展,电力的消耗不断增加,如何高效管理和监测用电成为了一个重要的课题。传统的电表只能提供简单的用电计量,无法满足现代家庭和工业对用电数据实时监控、远程控制及数据分析的需求…...
博弈论1:拿走游戏(take-away game)
假设你和小红打赌,玩“拿走游戏”,输的人请对方吃饭.... 你们面前有21个筹码,放成一堆;每轮你或者小红可以从筹码堆中拿走1个/2个/3个;第一轮你先拿,第二轮小红拿,你们两个人交替进行;拿走筹码堆…...
【人工智能解读】神经网络(CNN)的特点及其应用场景器学习(Machine Learning, ML)的基本概念
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默, 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把…...
Spring Cloud与Spring Cloud Alibaba:全面解析与核心要点
Spring Cloud与Spring Cloud Alibaba:全面解析与核心要点 一、引言 在当今的分布式系统开发领域,Spring Cloud和Spring Cloud Alibaba都是极为重要的框架。它们为构建大规模、高可用、分布式的应用系统提供了丰富的工具和组件。本文将深入探讨Spring C…...
Java 泛型
1. 泛型 (1) 泛型:定义类、接口、方法时,同事声明了一个或多个类型变量(如<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。可以在编译阶段约束要操作的数据类型 public static void main(String[] args) {//没加泛型 可以放任何…...
CentOS7 搭建 MQTT(mosquitto)环境并收发数据
零:说在前面 最近在研究物联网相关内容,需要接收 Modbus 协议的数据。上游数据源提出由对方整合数据后使用 MQTT 协议将数据发送过来,因此需要了解一下什么是 MQTT。 首先,它是一个类似 kafka 的“发布/订阅”模式的消息框架&…...
操作系统课后习题2.2节
操作系统课后习题2.2节 第1题 CPU的效率指的是CPU的执行速度,这个是由CPU的设计和它的硬件来决定的,具体的调度算法是不能提高CPU的效率的; 第3题 互斥性: 指的是进程之间的同步互斥关系,进程是一个动态的过程&#…...
Mac Goland dlv 升级
Mac Goland dlv 升级 问题表现 WARNING: undefined behavior - version of Delve is too old for Go version 1.22.1 (maximum supported version 1.21)查看当前Goland dlv 版本 ☁ ~ /Applications/GoLand.app/Contents/plugins/go-plugin/lib/dlv/mac/dlv version Delve…...
vue使用pdfh5.js插件,显示pdf文件白屏
pdfh5,展示文件白屏,无报错 实现效果图解决方法(降版本)排查问题过程发现问题查找问题根源1、代码写错了?2、预览文件流的问题?3、pdfh5插件更新了,我的依赖包没更新?4、真相大白 彩蛋 实现效果图 解决方法…...
【FFmpeg】FFmpeg 内存结构 ⑥ ( 搭建开发环境 | AVPacket 创建与释放代码分析 | AVPacket 内存使用注意事项 )
文章目录 一、搭建开发环境1、开发环境搭建参考2、项目搭建 二、AVPacket 创建与释放代码分析1、AVPacket 创建与释放代码2、Qt 单步调试方法3、单步调试 - 分析 AVPacket 创建与销毁代码 三、AVPacket 内存使用注意事项1、谨慎使用 av_init_packet 函数2、av_init_packet 函数…...
[Unity Shader] 【游戏开发】【图形渲染】Unity Shader的种类2-顶点/片元着色器与固定函数着色器的选择与应用
Unity 提供了不同种类的 Shader,每种 Shader 有其独特的优势和适用场景。在所有类型的 Shader 中,顶点/片元着色器(Vertex/Fragment Shader)与固定函数着色器(Fixed Function Shader)是两种重要的着色器类型。尽管它们具有不同的编写方式和用途,理解其差异与应用场景,对…...
Unity 动画曲线研究(Dotween插件)
动画的曲线的介绍 动画曲线(Animation Curve)是一种用于描述动画属性值随时间变化的图形工具。 我们可以通过给自己的动画片段设定不同的动画曲线,使动画效果具有不同表现力。 常见的动画曲线设定有: 线性(Linear&…...
适合小白的超详细yolov8环境配置+实例运行教程,从零开始教你如何使用yolov8训练自己的数据集(Windows+conda+pycharm)
目录 一、前期准备所需环境配置 1.1. 虚拟环境创建 1.2 下载yolov8源码,在pycharm中进行配置 1.2.1 下载源码 1.2.2 在pycharm终端中配置conda 1.3 在pycharm的terminal中激活虚拟环境 1.4 安装requirements.txt中的相关包 1.5 pip安装其他包 1.6 预训练…...
Linux中输入和输出基本过程
1.文件内核级缓冲区 前面在如何理解Linux一切皆文件的特点中提到为了保证在Linux中所有进程访问文件时的方式趋近相 同,在f ile 结构体中存在一个 files_operations 结构体指针,对应的结构体保存所有文件操作的函 数指针(这个结构体也被称为…...
二、FIFO缓存
FIFO缓存 1.FIFO缓存介绍2.FIFO缓存实现3.FIFO缓存总结 1.FIFO缓存介绍 FIFO(First-In-First-Out)缓存 是一种简单的缓存淘汰策略,它基于先进先出的原则来管理数据。当缓存达到容量限制并需要淘汰元素时,最先进入缓存的元素会被移…...
Linux_挂载nas
1、安装挂载nas必要的服务 yum -y install nfs-utils rpcbind 2、挂载nas sudo mount -t nfs -o vers3,nolock,prototcp,noresvport <NAS-IP>:/path/to/shared /yourNasPath mount 命令详解: -t :文件系统类型 ,这里指定的挂载类…...
uni-app开发AI康复锻炼小程序,帮助肢体受伤患者康复!
**提要:**近段时间我们收到多个康复机构用户,咨询AI运动识别插件是否可以应用于肢力运动受限患者的康复锻炼中来,插件是可以应用到AI康复锻炼中的,今天小编就为您介绍一下AI运动识别插件在康腹锻炼中的应用场景。 一、康复机构的应…...