OC 基础:基本语法

本文详细介绍了Objective-C的基础语法,包括构建简单类、定义多参数方法、点语法支持的set/get属性、@class关键字、Category和Protocol的使用,以及Block的概念和应用。通过实例展示了OC中如何创建对象、声明方法以及如何使用Block进行回调操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、构建一个简单的类

OC中的类分两个文件,.h用来声明类的变量和函数,.m文件负责实现,与.h配合使用。

OC中最根本的类叫NSObject,OC是单继承的。

声明类以@interface开头,以@end结尾,实现类用@implementation开头,以@end结尾。

继承用冒号。

OC当中使用一个类时,导包就是#import一个类的头文件。

声明类时,成员变量要声明在大括号中,方法声明在大括号外,如果是对象方法要写-号静态方法要写+号,所有在.h文件当中声明的方法都是公共方法,凡是类型,都要写括号,在方法名后,一个参数要一个括号,如:

//Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject {
    int age;
}
-(int)getAge;
-(void)setAge:(int)age;
@end
实现类时,首先要导入.h的声明.
//Student.m
#import "Student.h"
@implementation Student
- (int)getAge {
    return age;
}
- (void)setAge:(int)newAge {
    age = newAge;
}
@end


2、对象的创建

对象的创建需要调用类的静态方法alloc分配内存。  

调用静态方法要写[],里面是类名和方法名,返回值需要用指针来接收,也就是说,OC中的对象都要写个*。比如这句话调用了Student的一个静态方法alloc分配内存,并返回了一个指针来接收,其实alloc方法返回的是id类型,可以暂时理解为任何类型

Student *stu = [Student alloc];

分配内存后要调用一个动态方法进行初始化,相当于stu指针给Student发送了一个init消息:

stu = [stu init];

也就是说定义一个变量需要两句话,但是很麻烦,所以可以连起来写,这种方法最常用:

Student *stu = [[Student alloc] init];

3、定义有多个参数的方法

- (void)setAge:(int)newAge andNo:(int)newNo{
    age = newAge;
    no = newNo;
}

调用:

[stu setAge:100 andNo:1];

也就是说方法名可以拆成多个部分。

注意,这里的方法的方法名是setAge:andNo:,冒号也是方法名的一部分,代表有输入参数。在使用@selector(method)时要注意加上冒号。

4、set / get属性支持点语法

OC中的get方法不推荐使用get前缀,都是直接写变量名,比如[stu age];。

OC也支持点语法,比如:person.age = 10; 

不过这句话并不是java那样给成员变量赋值,而是调用了对应的set方法,在编译的时候会自动转化为方括号的语法。

如果点语法在等号左边,则调用set方法,在右边则调用get方法。为了和成员变量加以区分,OC推荐成员变量都以 _ 开头

set方法当中,绝对不能调用self.age=newAge,根据上面的解释,这种写法会死循环。同样在get方法里也不能return self.age。在OC当中用点语法来表示get/set方法。

5、OC属性机制

在.h 文件中做属性声明:

#import <Foundation/Foundation.h>
@interface Student : NSObject {
    int _age;
}
@property int age;
@end

当编译器遇到原型关键字时,会自动把这行代码展开成get和set方法的“声明”,并自动生成一个“同名”的“私有”的成员变量,通常习惯把成员变量定义成_age

如果我们手动实现了get或set方法,那么就不会生成对应的方法了。

6、@class 关键字

如果一个类持有另一个类,而且在.h文件里使用#import "Book.h"导入的话,会把.h全拷过去,性能会受影响,而且getset等方法也会暴露出去,一般不这么写,习惯在.h文件里使用关键字:@class Book;,只要知道Book是个类就可以了,在.m文件里真正要用到类里的方法时,再使用#import "Book.h"来获取其中的方法。一个典型的错误就是A类improt了B类,B也improt了A类,这样就会死循环而报错。而且,如果有多个文件同时improt了一个头文件,那么一旦这个头文件发生了改变,其他引用它的文件都要重新编译,而@class不存在这个问题。

需要注意的是,如果是继承某个类,就一定要improt头文件,因为这样才能知道它里面定义了什么方法。如果只是定义成员变量或属性,就@class。

7、Category(分类)

Category(分类)可以动态地给已经存在的类添加方法,类似C#的扩展方法。需要新建一个文件,类型是OCcategory,在Category on当中选择目标类,会生成“类名+分类名”.h和.m两个文件,生成的类名右边括号里就是分类名。需要注意的是这个类的.h文件里必须import原始类,不能@class,原因是要知道原先类里有什么方法。

#import "Student.h"
@interface Student (Test)
-(void)test2;
@end
#import "Student+Test.h"
@implementation Student (Test)
-(void)test2{
    NSLog(@"调用了test2方法");
}
@end
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Student+Test.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Student *stu = [Student student];
        [stu test2];
    }
    return 0;
}

8、Protocol(协议)

协议的声明看起来比较类似于Java中一个类的接口,但是和接口不同的是:协议没有父类不能定义实例变量

协议是一种特殊的程序设计结构,用于声明专门被别的类实现的方法。

协议在以下场合非常有用:

 1、需要由别的类实现的方法

 2、声明未知类的接口

3、两个类之间的通信 协议的基本特点

协议特点

 1、协议可以被任何类实现的方法

 2、协议本身不是类,它是定义了一个其他类可以实现的接口

3、类别也可以采用协议(用的不多) 协议中的关键字

协议关键字

1、@required:表示必须强制实现的方法

 2、@optional:表示可以有选择性的实现方法

范例:

  •  1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  •  //协议的声明
    #import <foundation foundation.h="">
    @protocol OneProtocol <nsobject>
     
    //可以选择实现的方法:
    @optional
    -(void) optionalMethod1;
    -(void) optionalMethod2;
    //必须实现的方法:
    @required
    -(void) requiredMethod1;
    @end

  • //采用协议(Test.h)
    #import "OneProtocol.h"
    @interface Test : NSObject<oneprotocol></oneprotocol></nsobject></foundation>
  •  1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  •  #import "Test.h"
     
    @implementation Test
     
    -(void)optionalMethod1{
        
    //可选择实现方法1
    }
    -(void)optionalMethod2{
        
    //可选择实现方法2
    }
    -(void)requiredMethod1{
        
    //必须是实现方法2
    }
    @end
  •  1
    2
    3
    4
    5
  •  Test *test=[[Test alloc]init];
           
    [test optionalMethod1];
           
    [test optionalMethod2];
           
    [test requiredMethod1];
           
    [test autorelease]; 

9、Block

 Block封装了一段代码,可以在任何时候执行,类似于函数指针,也类似C#的Func和Action,它用尖括号定义,可以做参数注入lambda,也可以做回调,比如:

int (^Sum)(int,int) = ^(int a, int b) {
        return a + b;
};
 
int a = Sum(10,11);

在block里是可以使用花括号外的变量的,但是不能修改它,类似java在外部加一个final,除非加一个关键字__block就能改变了,比如: 

void test() {
    __block int c = 1;
    int (^Sum)(int,int) = ^(int a, int b) {
        c = 10;
        return a + b + c;
    };
    NSLog(@"%i", Sum(1,2));
}

另外可以提前声明block的类型:

typedef int (^MySum) (int,int);

这样就可以用这个类型来定义block了:

MySum sum = ^(int a, int b) {
    return a+b; 
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值