【Object-C】对 Object-C 面向对象语法的理解

本文适合其他语言已经有经验,看到 Object-C 的代码觉得 Holly shit 想快速理解的读者

Objective-C最大的特色是承自Smalltalk的消息传递模型(message passing) —— 菜鸟教程

一个静态语言(如 c),如果代码中没有实现某方法但是程序中存在调用,那么编译器一定会报错;
但是实现了消息传递模型的 Object-C 不会,因为调用是发送一条信息,发信息是没有错的。信息接收者收不到只会导致在程序中抛出异常。

这一最大的不同就导致了 C、java、python 等一系列语言和 Object-C 语言在方法调用风格上的区别。

我们最容易理解的调用形式是:

obj.method(argument);

实例 obj 调用方法 method,参数是 argument

而 Object-C 中却是:

[obj method: argument];

向 obj 的 method 传递信息 argument

其次,这套信息传递的机制只用于面向对象相关的内容。Object-C 是 C 的超集,也就表明 C 中的代码和方法调用的语法仍然可以不经修改正常使用,也就导致最终 Object-C 中中括号的调用机制和正常的调用机制并存的局面。

知道了这两点,下面就只需要明白,基于消息传递模型的方法怎么定义、怎么调用即可。

类和接口的定义

由于这套机制基于面向对象,因此首先仍需要了解类和接口的定义方法。

类/接口的定义包含四部分:

  • 头尾区间声明
  • 类方法和继承关系声明
  • 结构体数据结构定义(Optional)
  • 方法定义(Optional)

其中数据结构和方法定义都是可选的,比如下面定义的内容是可以通过的:

#import <Foundation/Foundation.h>

@implementation My : NSObject
@end

int main(int argc, char **argv) {
    My *res = [My new]; // 实例创建
}

下面贴一个来自菜鸟教程的一个比较完备的例子(有一些修改):

@interface Myimp : NSObject {
    int memberVar1; // 实体变量
    id  memberVar2;
}

+(return_type) class_method; // 类方法
-(return_type) instance_method1; // 实例方法
@end

@implementation Myimp {
}
+(return_type) class_method {
    .... //method implementation
}
-(return_type) instance_method1 {
     ....
}
@end

基于上面的类创建一个实例,仍然使用信息传递模型:

Myimp *res = [Myimp my];

可以看成是向 类 Myimp 发送了一个

方法定义

类的声明定义完了,之后介绍类中的方法如何定义

下面定义的所有方法(带+/- 号的)都省略了在类上下文,都是仅在类的定义中才能用的。同时,假设类名为 Myimp


区分接口和实现

接口和实现的区别只差一个实现

下面是两个最简单形式的接口和相应实现的代码,可以看到接口在方法声明完后直接 ;,而实现还会有具体的逻辑代码。

- (void)func:(int)a :(float)b;
- (void)func:(int)a asd:(float)b {

}

为了节省空间,下面只用接口的代码演示定义和调用过程。

无参数

无参数方法最容易理解了:

- (void)func;

调用也很好理解:

Myimp *res = [Myimp my];
[res func];

一个参数

从有参数开始,多了一个冒号

@interface My : NSObject
- (void)func:(int)a;
@end

调用也会多一个冒号:

[res func:5];

仍然还比较好理解

多个参数

多个参数就会有多个冒号,但除了多出一个冒号,还可以多出额外的一些内容,比如对参数的说明。
以下两种声明都是正确的:

- (void)func:(int)a :(float)b;
- (void)func:(int)a toB:(float)b;

但是对不同的声明,调用方式会有区别:

- (void)func:(int)a :(float)b;
[res func:5 :6];

- (void)func:(int)a toB:(float)b;
[res func:5 toB:6];

我们会发现,从第二个参数开始,我们可以对每个参数加一个额外的词(注释?key?需要调研一下官方怎么叫)。

从表现上,可以把函数声明中的 toB 看成是消息传递时的 key,这个 key 只能在调用时用,在方法体内用类型之后的那个参数名,比如:

- (void)func:(int)a toB:(float)b toC:(double)c {
    printf("%f%f%f", a, b, c);
}

但即使有了这个 key,在调用时也必须按参数定义顺序来调用:

[res func:3 toB:4 toC:5];

变长参数

暂时没遇到使用场景,偷个懒,随便放个介绍链接,以后填坑。
https://blog.csdn.net/weidfyr/article/details/48263315

Reference

  • https://blog.teamtreehouse.com/the-beginners-guide-to-objective-c-methods
  • https://www.runoob.com/w3cnote/objective-c-tutorial.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值