ObjectiveC-04-类的创建以属性、方法定义详细

在本小节中,笔者会详细讲解下ObjC的类的相关内容,包括创建、构造、方法、属性以及属性读取等相关知识,先来看下类的组成:

在这里插入图片描述

类的创建

ObjC是在C语言基础上扩展的,在编写OS软件时可以混用两种语言。但它们之间是有区别的,C是面向过程的语言,而ObjC则是定位成一种OOP语言,所以本文档中基本是以ObjC语言为主,少量的会用C来编写(原因是C的性能会好一些)。

在objc中只要看到@符号,就可以把它看成是对C语言的扩展;

此处先讲一点ObjC面向对象的代码编写知识,后续会再详细描述OOP内容。OOP语言中的对象一般统称为类,ObjC也不例外,定义一个ObjC类时比java语言要麻烦一些,ObjcC类需要以下部分的组合;

在Xcode中新建类的方法如下,右键选择项目文件夹,然后选择 New File,比如创建一个名为Fraction的类。

在这里插入图片描述
创建完成生会生成两个源文件,这种源码格式需要适应,后面还有一种更简单的方式,会在本小节最后面介绍下。
在这里插入图片描述

类对象声明@interface

用关键字@interface来定义,这个关键字定义新类时首先需要告诉编译器类此类来自何处,这种设计方式是一个好的习惯,尤其是在一些更高级的语言中比如java不会限制源文件的名称必须一致,ObjC语言所有类的超类是NSObject,如果无特殊设计,一般自定义的类都会继承NSObject。然后在此接口中就可以定义属性和方法了,语法格式如下:

/*语法格式*/
#import <Foundation/Foundation.h>

@interface newClassName: parentClassName{ //一般为NSObject
     //propertyDeclarations
}
    //methodDeclarations
@end // newClassName

demo示例,下列代码中的NS_ASSUME_NONNULL_BEGIN是可有可无的,其它的符号会在后续详细说明。

//demo示例
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Fraction : NSObject
{//属性定义
@private
    int size;
    int length;
}

//方法定义,此处通常是顶格写的
- (void) print;
- (void) setNumerator: (int) n;
- (void) setDenominator: (int) d;

@end

NS_ASSUME_NONNULL_END

类对象实现@implementation

类实现用@implementation关键字来指定,它与interface是配套的。语法如下:

//语法格式
@implementation newClassName{
     memberDeclarations; //类变量
}
    methodDefinitions; //方法实现
@end

demo示例
@implementation Fraction {
    int numerator;
    int denominator;
}
- (void) print {
    NSLog(@"%i / %i", numerator, denominator);
}

- (void) setNumerator:(int) n {
    numerator = n;
}

- (void) setDenominator:(int) d {
    denominator = d;
}
@end

需要注意:

  1. 定义@implemention与@interface的文件名称相同;
  2. implementation可以不实现全部的interface中定义的函数声明,但未实现的方法调用在运行时会报异常;
  3. 如果在.m中选择性的实现在.h中定义的方法,在调用时可以使用respondsToSelector等函数来进行安全检查;

类对象调用

此示例中我们用main函数来调用上述自定义的类对象

#import "Fraction.h"
int main(int argc, char* argv[]){
    @autoreleasepool {
        Fraction *myFraction; //表明myFraction是一个对象的引用(指针)
        myFraction = [Fraction alloc]; //alloc表示要分配新的内存空间,返回存储数据的引用
        myFraction = [myFraction init]; //初始化类
        
        //上述三行代码可以合并为一行代码,即 Fraction *myFraction = [[Fraction alloc] init]

        [myFraction setNumerator:1]; //函数调用
        [myFraction setDenominator:3];

        [myFraction print];
    }
    return 0;
}

也可以改成如下的简单测试方法调用

#import "Fraction.h"

void fractionTest(){
    Fraction *fraction = [[Fraction alloc] init];
    [fraction setNumerator:1];
    [fraction print];
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        fractionTest();
    }
    return 0;
}

构造函数

类可以使用new和alloc init的方式来初始化对象,推荐后者, 在NSObject提供的init函数用于类对象的初始化,类似于java中的构造函数的概念,所以默认所有的自定义对象都有一个init方法(可以覆写)。

//alloc申请一块内存空间,同时也会设置一些属性的默认值保证类可用
//init可以有多个用于初始化类属性
Fraction *fraction = [[Fraction alloc] init];

覆写默认构造函数

(instancetype) init{  //instancetype也可换成id
    if(self = [super init] }{ //调用父类的初始化方法
        //个性化代码
        NSLog(@"FRACTION INIT");
    }
    return self; //返回实例对象
}

自定义多构造函数

同时也支持多构造函数,比如Foundation框架中提供的NSArray类。

- (instancetype)initWithString:(NSString *)aString;
- (instancetype)initWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
- (instancetype)initWithFormat:(NSString *)format arguments:(va_list)argList NS_FORMAT_FUNCTION(1,0);

//用myInitArrayValue变量初始化,即initWithArray是个有参数的方法
NSArray *myArray = [[NSArray alloc] initWithArray:myInitArrayValue];

自定义的类也可以仿写成NSArray那样类似initXXX的初始化方法,如下:

@interface Fraction:NSObject
- (instancetype) initWith: (int)n;
- (Fraction *) initWith: (int)n;
@end
//覆写超类的初始化代码,这块代码可不写
@implemention Fraction
(instancetype) init{
    if(self = [super init] }{ //调用父类的初始化方法
        //个性化代码
        NSLog(@"FRACTION INIT");
    }
    return self; //返回实例对象
}

//方式1:
- (Fraction *) initWith: (int)n {
    self = [super init]; //此处也可以调用其它的初始化方法
    if(self){
        [self setTo:n over:3]; //执行初始化方法
    }
    return self;
}

//方式2:
- (instancetype) initWith: (int)n {
    self = [super init]; //此处也可以调用其它的初始化方法
    if(self){
        [self setTo:n over:3]; //执行初始化方法
    }
    return self;
}
@end

//测试程序
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Fraction *a = [[Fraction alloc] initWith:3];
    }
    return 0;
}

上述代码中初始化方法的返回值一般会用(id)或(instancetype)来代替,id是一个关键字可简单认为它是一个通用的对象类型,类似泛型的概念,所以一般会用改成如下写法:

- (id) initWith: (int)n {
    self = [super init]; 
    if(self){
        [self setTo:n over:3]; //执行初始化方法
    }
    return self;
}

属性定义

全局变量 extern 关键字

定义在类声明和类实现部分都可以(这样本类和其它类全可以访问了),但一般会定义在类声明部分,下面是一个例子说明在Fraction.m中定义一个全局变量,需遵循两点规定:

  1. 在所有的方法和函数之外声明;
  2. 一般变量名为g开头,表示这是一个全局变量;
#import "Fraction.h"

//全局变量
int gGlobalVar = 5; 

int main(int argc, const char * argv[]) {
    NSLog(@"%i", gGlobalVar);
}

这种全局变量一般用于跨类使用,如果在其它文件中使用,不需要import引用就可以直接用,但需要用到extern关键字声明一下,它表示告诉编译器要访问其它文件中定义的全局变量,比如在另一个类Foo中访问

- (instancetype) init {
    self = [super init];
    if(self){
        NSLog(@"FRACTION INIT");
        extern int gGlobalVar;
        NSLog(@"FRACTION INIT %i", gGlobalVar); //5
    }
    return self;
} 

一个好的实践是把全局变量定义在一个单独的类中或定义的main.m函数中;

不可变变量 const 关键字

有此修饰的变量的值不能被改变,相当于java中的final的作用。

        const char *words[4] = {"java", "c", "objc"};
        for (int i=0; i<sizeof(words); i++){
            NSLog(@"%s is %lu length", words[i], strlen(words[i]));
        }

静态变量 static 关键字

ObjC中的static变量是和java不太一样,在ObjC中没有static只能在static方法中使用的限制。ObjC中的静态变量主要是为了弥补全局变量的安全缺陷而增加的,因为全局变量作用域太大,如果只希望在本类中使用全局变量,则可以在原基础上加上static来修饰。

另外一个用处就是用static修饰的变量的值不会被释放,其属于常驻内存的一个常量。

#import "Fraction.h"

//作用域只即于本类的全局变量
static int gGlobalVar = 5; 

int main(int argc, const char * argv[]) {
    NSLog(@"%i", gGlobalVar);
}

私有变量 @private 标识

除以使用上述private标识,还可以使用public, protected, package这三个,这些其实并不是作用域的概念,这些标识和变量的内存位置有关,因为类的成员变量是存储在结构体中的。这些标识指的是能否通过指针的方式直接操作内存的结构体。

@interface Fraction : NSObject
{//属性定义
@private
    int size;
    int length;
}

比如一个Fraction类定义了一个numerator成员,并用@public来修饰,则就可以通过下面的方式来访问这个变量

Fraction *myFract = [[Fraction alloc] init];
myFract->numerator;

方法中的临时局部变量

局部变量其实就是定义在方法体中的变量,因作用域只局限于此方法

- (void) setName{
    int i = 1; //此变量就是局部变量
}

属性存取

类属性的存取就是属性的getter和setter方法,一般不建议直接通过属性名称的方式来设置和读取属性的值,最好封装到一个方法中,这样能获取最大的便利。在ObjC中其有一个特定的规范,比如:

int tire //属性名
- (void) setTire:(int)tire; //设置方法,加set前缀
- (int) tire; //读取方法,不加get前缀

不加get前缀,这是一个不成文的规定,因为Cocoa框架中的API带get前缀的函数表示返回传入参数的指针值。

通用实现

这种实现方式比较通用,但会写大量的代码。在现代的编程中可以使用新的特性,如果是比较老的应用只能用这种方法。

@interface AllWeatherRadial : NSObject
{
	float pressure;
	float treadDepth
}

- (float) pressure;
- (void) setPressure: (float *) pressure;

- (float) treadDepth;
- (void) setTreadDepth: (float *) treadDepth;

@end // AllWeatherRadial end
@implementation AllWeatherRadial

- (float) pressure{
    return pressusre
}
- (void) setPressure: (float *) pressure{
    pressusre = pressusre;
}

- (float) treadDepth{
    return treadDepth;
}
- (void) setTreadDepth: (float *) treadDepth{
    treadDepth = treadDepth;
}
@end // AllWeatherRadial end

使用注解@property

@property是一种新的编译器功能,它意味着声明了一个新对象的属性,编译器还会自己生成getter和setter方法,用这种特性简化上面的代码如下:

#import <Foundation/Foundation.h>

@interface AllWeatherRadial : NSObject

@property float rainHandling;
@property float snowHandling;

@end
#import "AllWeatherRadial.h"

@implementation AllWeatherRadial

/*这两行代码不是必须的,它只是一种get/set预生成器指令,但在Xcode4.5版本后可以不写*/
//@synthesize rainHandling;
//@synthesize snowHandling;

- (NSString *) description{
    NSString *desc;
    desc = [[NSString alloc] initWithFormat: @"AllWeatherRadial: / %.1f / %.1f",
               [self rainHandling],
               [self snowHandling]];

    return (desc);
}
@end

测试代码

#import <Foundation/Foundation.h>
#import "AllWeatherRadial.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        AllWeatherRadial *item = [[AllWeatherRadial alloc] init];
        [item rainHandling];
        [item setRainHandling:2.2];
        NSLog(@"%@", item);
    }
    return 0;
}

@property指令详细

因为@property是一种自动生成代码的指令,所以也需要有一些灵活的配置。比如添加一个内存回收机制,是否允许生成代码等,以下是这引指令常用的修饰符,可多个同时使用。

@property (readonly, nonatomic) NSString *name;
  • weak/strong:引用类型,常用
  • nonatomic:线程不安全,常用
  • atomic:线程安全,系统会生成互斥的getter和setter方法,常用
  • readonly:只读属性,不会生成setter方法
  • readwrite:默认
  • assign:默认编译器
  • nullable:是否可为空
  • retain:保留和内容释放有关
  • null_resettable、null_unspecified:老版本遗留的不太使用了,变量引用相关
  • setter/getter:自定义方法名,如@property (setter=isHidden) BOOL hidden;这样编译器就会自动生成一个名为isHidden的方法做为setter方法;

如果使用了@property指令定义属性,则在实现类中可用以下方式访问

@interface AllWeatherRadial : NSObject
@property float rainHandling;
@end

@implementation AllWeatherRadial

- (void) propertyGetter{
    [self rainHandling]; //调用rainHandling()方法
    self.rainHandling;  //调用rainHandling()方法
    _rainHandling;  //直接读取属性
}
@end

@synthesize指令详细

如果不想用上面带下划线(直接读取属性)的方式调用,就需要用到 @synthesize 关键字重新声明一次。

  1. 有一点需要注意的是,使用这个指令时,属性的名称不要以new、alloc、copy、init开头;
  2. 使用了@property指令后,省略了@synthesize时,则编译器会默认把property声明的属性名称最前面加上下划线,比如name变成_name;
@interface AllWeatherRadial : NSObject
@property float rainHandling;
@end

@implementation AllWeatherRadial
@synthesize rainHandling
- (void) propertyGetter{
    rainHandling;  //直接读取属性,这样就不用前面加_了
}
@end

@dynamic指令

这个指令比较简单,就是阻止自动生成getter/setter方法

#import <Foundation/Foundation.h>

@interface AllWeatherRadial : NSObject

@property float rainHandling;
@property float snowHandling;

@end

//---------------------
@implementation AllWeatherRadial

@dynamic rainHandling;

- (NSString *) description{
    NSString *desc;
    desc = [[NSString alloc] initWithFormat: @"AllWeatherRadial: / %.1f / %.1f",
               [self rainHandling], //这处会报错,因为上面阻止生成了存取方法
               [self snowHandling]];

    return (desc);
}
@end

方法定义

在objc中会区分类方法和实例方法,比如alloc就是一个类方法,而init就是一个实例方法。

  1. -:减号定义实例方法,必须实例化类后才能使用;
  2. +:加号用来定义类方法,相当于static方法,可以不实例化类直接使用;

消息:接收者+方法名+参数三部分组成,在ObjC中方法调用有时称为消息发送,消息的格式其实就是[NSObject alloc]这样的格式,前面是接收者,后面是方法名

语法格式

注意参数的定义格式,参数名称这个东西这点和python比较类似。

无参函数
在这里插入图片描述

有参函数:建议的是第二种格式。
在这里插入图片描述

  1. 有参数时需要在方法名称后加一个冒号:,否则直接以分号或{}结尾即可;多个参数以冒号:相连;
  2. (int) n,必须要指定其类型,参数名称任意,例如:- (int) getNumerator;
  3. ObjC语言中如果参数或变量是一个引用类型,则需要加一个*号,例如:- (NSString *) getNumerator: (NSString *) val;

返回类型:如果有返回值,需要在方法实现的最后加一个return语句;
在这里插入图片描述

返回值

  1. 返回值为基本数据,则直接用 () 包装即可,比如 (int);
  2. 返回值为指针(对象),则需要用( *)包装,比如(NSString *);

示例程序

// 无返回值,无参数
- (void) createLabel{
}

//有返回值 ,无参数
- (BOOL) createLabel{
    return YES;
}

- (NSTextField *) createLabel{
    NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 280, 20)];
    return label;
}

//无返回值,有一个参数
- (void) formRichLabel:(NSTextField *) richTextLabel{

}

//无返回值,有多个参数,参数名+类型,第一个参数不需要指定参数名
- (void)addAttribute: (NSAttributedStringKey)name 
                      value:(id)value 
                      range:(NSRange)range{
}

//用const关键字,定义为不可变参数
- (void) setTo: (const int) n over:(int) d

事实上,参数名是可选的,如下实现与上述等价,但是如果定义了名称则所有的实现和调用都需要带名称。

//方法定义
- (void) setTo: (int) n :(int) d

私有方法

严格来讲这并不是私有方法,因为ObjC没有私有这一定义,只是为了一些编程方便,设置在实现类中的一些私有方法。多数充当测试和工具类使用。

#import <Foundation/Foundation.h>

NSString *bool2Str(BOOL y){
    if (y == YES){
        return @"yes";
    }else{
        return @"no";
    }
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!\n");
        printf("Hello, World!\n");
        
        NSLog(@"%d = %@", 1, bool2Str(1));
        NSLog(@"%d = %@", YES, bool2Str(YES));
    }
    return 0;
}

类的描述

在上面的程序中,如果通过NSLog()函数可以打印一个类的实例,一般只会打印一个内存地址出来,如果想变成一个可读性更强的文案就需要覆写NSObject对象提供的description方法(此方法和java的toString类似)。

descritpion 方法

在ObjC中NSLog(@"%@)调用的就是对象的description方法,此方法直接在实现中写即可,不需要在接口中定义,因为它是在NSObject中实现的,下面例子演示了自定义类的描述信息的方法,注意下面两种方式实现的不同

+ (NSString *)description{
    return @"aaa";
}
NSLog(@"%@", s);
NSLog(@"%@", [Rectangle description]);

/*
<Square: 0x10110d950>
aaa
*/
- (NSString *)description{
    return @"aaa";
}

Rectangle *s = [[Square alloc] init];
NSLog(@"%@", s);
NSLog(@"%@", [Rectangle description]);

/*
aaa
Rectangle
*/

推荐的方式是声明为 - ,因为它会打印出更多信息

- (NSString *)description{
    NSString *str = [[NSString alloc] initWithFormat:@"size=%d length=%d", size, length];
    return str;
}

/*
size=5 length=6
Rectangle
*/

class 方法

在ObjC中也有和java一样的一个class方法,比如得到当前类的类型:

 [Complex class] //Complex是一个自定义的类
 if([ob1 class] == [ob2 class]) //比较两个类是否是同一类型

sizeof 内存大小

这个方法可以打印当前对象、变量等占用的内存大小,单位为byte。

//基本数据大小
int a[3] = {1,2,4};
sizeof(a);//~~12

//对象大小
sizeof(*myFract); 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全球X射线源市场持续增长 我国高端产品研制能力较弱

全球X射线源市场持续增长 我国高端产品研制能力较弱 X射线源&#xff0c;即X射线发生器&#xff0c;是产生和发射X射线的装置&#xff0c;从阴极发射电子&#xff0c;经阴极与阳极之间的电场加速后&#xff0c;高速轰击阳极靶面&#xff0c;产生X射线射出&#xff0c;是X射线检…

LeetCode.2908. 元素和最小的山形三元组 I

题目 2908. 元素和最小的山形三元组 I 分析 首先&#xff0c;看到这道题&#xff0c;第一反应就是暴力方法&#xff0c;三层for循环&#xff0c;枚举每一种情况&#xff0c;代码如下 class Solution {public int minimumSum(int[] nums) {int min Integer.MAX_VALUE;for(i…

Linux 进程信号:内核中信号结构、阻塞信号、捕捉信号

目录 一、阻塞信号 1、信号的状态 2、内核中的信号 信号集&#xff08;Signal Set&#xff09; task_struct 结构体 信号处理函数&#xff08;Handler&#xff09; 信号传递与调度 3、“signal_struct结构体”与“信号集sigset_t” 4、信号集操作函数 5、信号屏蔽字si…

【Hadoop大数据技术】——Hive数据仓库(学习笔记)

&#x1f4d6; 前言&#xff1a; Hive起源于Facebook&#xff0c;Facebook公司有着大量的日志数据&#xff0c;而Hadoop是实现了MapReduce模式开源的分布式并行计算的框架&#xff0c;可轻松处理大规模数据。然而MapReduce程序对熟悉Java语言的工程师来说容易开发&#xff0c;但…

还在问要不要学Python?看完这篇你就知道了

前不久教育界的一个消息&#xff0c;引发了广泛的关注。 今年9月开学后&#xff0c;浙江三到九年级信息技术课将替换新教材&#xff0c;八年级将新增Python课程内容。新高一信息技术编程语言由VB替换为Python&#xff0c;大数据、人工智能、程序设计与算法按照教材规划五六年级…

抽象类和接口(java初识)

1.抽象类 1.1抽象类的概念 在面向对象中&#xff0c;所有对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息描绘一个具体的对象&#xff0c;这样的类就是抽象类。 例子&#xff1a; 说明…

【C语言终章】预处理详解(上)

【C语言终章】预处理详解&#xff08;上&#xff09; 当你看到了这里时&#xff0c;首先要恭喜你&#xff01;因为这里就是C语言的最后一站了&#xff0c;你的编程大能旅途也将从此站开始&#xff0c;为坚持不懈的你鼓个掌吧&#xff01; &#x1f955;个人主页&#xff1a;开敲…

代码随想录算法训练营三刷 day38 | 动态规划之 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

三刷day38 509. 斐波那契数1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 70. 爬楼梯1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 746. 使用最小花费爬楼梯1 确定dp数组以及下标…

经验分享:开源知识库才是企业低成本搭建的最佳选择!

身为企业所有者的你&#xff0c;是否为建设企业的知识库而头疼&#xff1f;想要一个功能全面而又简单易用的知识库&#xff0c;但又担心成本过高&#xff1f;那我今天要分享的内容&#xff0c;可能会给你带来一些启示。那便是&#xff1a;开源知识库便是你企业低成本搭建的最佳…

Stable Diffusion 模型下载:epiCPhotoGasm(真实、照片)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 该模型对照片是什么有很高的了解&#xff0c;所以…

Arcgis获取乡镇矢量

现有全中国乡镇矢量边界&#xff08;2023年&#xff09;&#xff0c;如何获取其中的自己所需的子区域&#xff08;一个小镇&#xff09;呢&#xff1f; 可以先去查一下自己的镇代码&#xff0c;我查的是东马圈镇代码 打开分析工具-提取分析-筛选 刚刚记下了FID 验证一下&am…

武汉星起航:引领跨境电商新纪元,助力卖家实现全球业务飞跃

在全球化的时代背景下&#xff0c;越来越多的中国卖家正选择跨境电商作为他们拓展国际市场的重要途径。然而&#xff0c;对于许多新手卖家而言&#xff0c;如何进入海外市场、如何运营店铺、如何推广产品&#xff0c;都是一道道难以逾越的难题。在这个关键时刻&#xff0c;武汉…

词令用户常说的:词令关键词口令直达与词令关键词直达口令有什么区别?

词令是一种通过输入特定关键词令&#xff0c;直达该词令关联的网站、页面、程序、应用、功能、服务或目标的工具。词令可以帮助用户更快速、更便捷的直达目标的提效软件。而词令用户常说的&#xff1a;词令关键词口令直达与词令关键词直达口令有什么区别&#xff1f; 词令关键词…

【多模态对比学习】我遇到的坑

对比学习踩坑记录 本文是对过去几个月来利用对比学习的思想来优化多模态学习任务的思路的总结&#xff0c;主要包含以下几个方面&#xff1a;为什么要用对比学习、跨模态中对比学习怎么用、对比的过程中负样本是不是越多越好、要不要推远所有的负样本、样本之间的语义碰撞如何缓…

低噪声、轨至轨运算放大器芯片—— D721、D722、D724,适合用于音频领域

应用领域 D721、D722、D724是我们推荐的三款低噪声、轨至轨运算放大器芯片&#xff0c;其中D721为单运放&#xff0c;D722为双运放&#xff0c;D724为四运放。适合用于音频领域、传感器等的信号放大处理&#xff0c;比如K歌宝、音响、测距、滤波器、AD转换器前级信号处理等等。…

【Go】二、Go的基本数据类型

文章目录 0、进制1、变量的声明2、数据类型3、整型4、浮点型5、字符类型6、布尔类型7、字符串类型8、基本数据类型的默认值9、类型转换10、基本类型转String11、String转其他类型 0、进制 N进制&#xff0c;逢N进一 1、变量的声明 //声明 赋值 var age int 18//声明、赋值、…

基于单片机20v数字电压表仿真系统设计

**单片机设计介绍&#xff0c;基于单片机20v数字电压表仿真系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机20V数字电压表仿真系统设计是一个结合了硬件与软件设计的综合性项目。以下是对该设计概要的详细描述…

使用 CSS 实现多立方体悬停颜色效果实现

使用 CSS 实现多立方体悬停效果实现 效果展示 CSS 知识点 filter 属性的 hue-rotate 值运用使用 CSS 实现立方体 场景布局分析 从效果图可以看出&#xff0c;要实现 3*3 的立方体集合&#xff0c;我们需要考虑一下怎么安排小立方体的布局。我这里的做法是使用span实现单个小…

账号微服务短信验证码发送工具单元测试

账号微服务短信验证码发送工具单元测试 注意sms的 app-code #----------sms短信配置-------------- sms:app-code: dd7829bedfaf4373875aa91abba82523template-id: JM1000372package net.xdclass.config;import org.springframework.context.annotation.Bean; import org.spri…

klmanga 章节链接获取

两年前还是可以直接爬的&#xff0c;现在章节不显示了 直接爬取下来的源码章节显示loading&#xff0c;在源码中可以看到是通过js加载出来的&#xff0c;搜索loadChapterDate dataFile atob(FR)&#xff0c;这是将FR的值用base64解码赋予dataFile 根据这段var paramsnew …