Objective-C语法区分

这篇博客介绍了Objective-C作为iOS应用开发语言的特点,对比了它与其他语言如Java、C#的差异。Objective-C是在C语言基础上扩展,具有头文件和实现文件的区分,使用#import避免重复导入,同时Objective-C的类声明、属性和方法定义有其独特规则。文章还提到了Swift作为新语言的引入,但Objective-C仍广泛使用,因为大多数第三方工具是基于它。最后,博主分享了关于OC中类声明、协议、方法调用、super和self、id类型、分类以及扩展的相关知识。

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

苍苍,雪茫茫,风吹雾散见重


叶未落尽冬已到


对于从未接触过IOS发,却熟悉另一语言开发的人来说,Objective-C可能是不易被接受的,因为其除了一些基本概念如对象,MVC,持久化,继承等等和其他语言有相处外,不像Java,C#,安卓,VB语法那样有共通性

苹果开发除了使用苹果一体机和苹果笔记本外,大家还有以下选择

  1. 苹果mini,搭配上支持苹果端口的显示器,OK的,一台苹果mini 3000多,而且也是苹果官方。
  2. 黑苹果,自从苹果采用Intel后,国内出现了一批黑苹果,它可以很好的运行MAC OS X统,也不贵,不过苹果不提供升级,需要系统升级的时候,自己另找点花上不到100块升级下
  3. 如果你的电脑CPU支持硬件虚拟化的话,那么可以安装MAC拟机,或者拷贝现成的虚拟机。虽然没有真机快,不过也够用啦(如果内存够,虚拟机也是蛮顺畅的)
  4.  如果你的私人电脑够牛,你又有足够的勇气和耐心,那么可以从网上找教程给自己的笔记本装MAC双系统。如:http://blog.sina.com.cn/s/blog_613830e70101ezj3.html。试验证明,这一点可行,不过稍有不慎,硬盘坏掉也有可能试验不成功。一个成功的教程这台笔记本上能成功,另一台一样的可能就出新问题。抱着可能成功的信念不断试试试,也许你就能成功。不排除你是一次成功的案例。(我以前的例子是装坏了一台笔记本的硬盘,又换了个新的当时最适合装mac统的笔记本,试验了3个月,终于在考试前夕OK了。不过现在的笔记本应该好多了。

发语言:IOS 应用开发使用的是Objective-C语言,以及去年公布的Swift语言

对于熟悉其他语言的开发者来说,可能swift更好入门,不过由于90%的第三方工具是Objective-C,旧设备的不支持,现在市面上大部分还是在使用Objective-C,所以我们依然是使用Objective-C。但是大家不要担心以后会不会白学,因SwiftObjective-C除了语法有很大差别外,并不会影响开发,使用二者的UI设计,框架,编程思想等等哪怕是依托的类库都是完全相同的。我们这门课,讲解语法的也只占用一节而已,后面的其实都是共用的,所以知道swift的人也不用担心。SwiftIOS8之后才支持的,Objective-C支持所有版本,并不是说苹果废弃了

语法区别

可能记的不全,如果以后遇到,可以提出,我再更新。以下Objective-C简称为OC

OC是在C语言的基础上添加扩展而成,它可以调用C,但是OC本身实现与C又几乎完全不同,它自己定义了一些规则

  • 头文件和实现文件

这点OC类似于CC++,分为定义头文件(.h)和实现文件(.m),.h文件和CC++样,.m和他们的.c,.c++文件一样,C#java没有这个概念,它只是把类的声明定义与实现分开在两个文件中,也就是一个类会有两个文件,一个.h一个.m,你可能会看到单独的.h义文件,如定义一些枚举,常量类,协议等,但是不会有单独一个.m的情况。

  • 引用:

时我们会使用到类库中的方法或者调用其它类,大家都知道吧。这里只列出来,用法是一样的,只是规则这样写一样,你不要问我为什么是这样,这是OC规则或规约,就好像如果我讲的是C#java应该没人问:为什么是usingimport,而不是useinclude呢?吧。如果好奇,那我只能说,这是规约,记住它,OK?

JAVA

import java.io.IOException;

C#

using System;

OC

#import <Foundation/Foundation.h>
#import “TOSCommonDefinition.h”

#import会自动导入一次,不会重复导入,也就不会引起交叉编译

#import<>引用系统文件,它用于对系统自带的头文件的引用,编译器会在系统文件目录下去查找该文件.也可认为是动态链接库的头文件引用。
#import””:
户自定义的文件用双引号引用,编译器首先会在用户目录下查找,然后到安装目录中查找。.a态链接库里的头文件也是这样引用

  • 类声明和定义

JAVAC#

public class 类名 extends 父类名 implements 接口名{
private 属性类型属性名;
public 返回类型方法名(参数类型参数名,…) {
方法实现体
}
}

大家所见的定义是这样的吧,在一个文件中,声明了类,在{}中定义它的属性和方法体实现

OC中与其类似的是也有类声明和定义,继承和实现接口,只不过除了方法体实现是在.m文件中其他一般都在.h文件中,大家可能发现了我用的是一般这个后面我会介绍,因为有一些私有属性和方法定义我们是放在.m中的,这个涉及到类的扩展,后面讲

OC:(区别来喽

.h
@interface 类名 : 父类名<协议1,协议2,…>                                                 //①
{                                                  //②
@private 属性类型属性名1;                                                 //③
}                                                 //②
@property (变量属性) 属性类型属性名2;                                                     //④
+ (返回类型) 方法名1: (参数类型1)参数名1 参数标识: (参数类型2)参数名2 ;  //⑤
– (返回类型) 方法名2: (参数类型1)参数名1 参数标识: (参数类型2)参数名2 ;  //⑤
– (返回类型) 方法名3                                                                               //⑥
@end //⑦
.m
#import “该类头文件” //⑧
@implementation 类名//⑨
@synthesize 属性名2;//⑩
+ (返回类型) 方法名1: (参数类型1)参数名1 参数标识: (参数类型2)参数名2  //⑪
{
方法实现体
}
– (返回类型) 方法名2: (参数类型1)参数名1 参数标识: (参数类型2)参数名2
{
方法实现体
}
– (返回类型) 方法名3
{
方法实现体
}
@end //⑫

OK,一个简单的类结束了,有人可能会问,你这是定义的接口吧,怎么还实现了?NO这是一个再正常不过的Objective-C类。以上加粗部分都是区别,下面一个个说

1.    @interface类的声明。这个关键字和Java/C#义类时的class一个意思,是声明一个类,如果这里你有接口的悬念,先放肚子里。
类的定义放在@interface@end

2.    部分的【:】:代表这个后面跟着的是继承类,与Java/C#extends义。如果没有父类可以不

3.    部分的【<>】:代表这个里面是该类所实现的协议,与Java/C#implements义。如果没有实现的协议,可以不写
一个类只能有一个父类,但是可以实现多个协议

4.    部分的【{}】:属性在里面定

5.    部分的@private,和Java/C#private样,记得前面有【@】哦,代表访问权限,默认@private,另外还有@public,@protected,@package简单说
@private
:本类可以访问,子类不可以;
@protected
:本类和子类都可以访问,其他类不可以;
@public
:本类、类、其他类都可以;
@package:
对于framework内部,相当于@protected对于framework外部,相当于@pravite.我没有用到

6.    部分的@property属性声明,是不是疑问了“5里不就是属性定义吗?。在OC里,即使你定义了@public访问权限,外部也是不能.出来的哦,需要settergetter方法,这点和Java/C#get,set方法一样的。OC新加了@property@synthesize,如此声明的属性是@public的,会自动生成settergetter方法,而不用自己实现,是不是很方便。@property是声明,@synthesize.m里是其实现

7.    部分和⑥部分是方法定义,它与Java/C#不同:
*+
-+代表这个方法是类方法(类名调用),-实例方法(对象调用)。类方法有点类似Java/C#static态方法。是所有实例共享的
*
访问权限:在.h义的方法默认都是@public
*
返回值类型要用【()】括起来
*
参数类型要用【()】括起来
*
参数前面一定有【:】,【:】前可以有标识名也可以空,不过建议最好,且有实际意义,比如initParam:(Integer)height withWidth:(Integer) width,”withWidth”对后面参数有一个说明。
*
方法名:【方法名: 参数标识:】,没有参数的方法名才是【方法名】。比如【initParam:(Integer) height withWidth:(Integer) width】,方法名“initParam:withWidth:”,如果@selector(initParam)可是找不到方法的哦。
义的属性和方法都必须以【;

8.    部分:.m文件中一定会引用该类头文件的。必须的,否则,报错

9.    @implementation类的实现,后面跟类名。在.m文件,里面实现在.h扩展类中定义的方法或@property
类的实现放在@implementation@end

10. @synthesize以【;结尾,与头文件中@property一一对应

11. 部分就是方法实现体,本类的类方法、实例方法,协议的方法,扩展类的方法(私有方法

12. @end类定义体和实现体的结束标识,没有报错,就像上面Java/C#示例的【}

协议:(接口)

上面我们一直提到协议这个词,大家先把UDP/TCP等等抛出去,你们脑海中的协议在IOS中通用。我这里说的协议是@protocol,也就是Java/C#interface接口。它里面定义了一些方法列表,通过委托去调用,而<>了它的类都是它的委托类。和接口是一样的

Java/C#:

public interface 接口名
{
方法列表
}

OC

@protocol 协议名<协议名>

-方法1
-
方法2
@optional
-
方法3
-
方法4
@required
-
方法4

@end

协议也可以继承父协议,这样实现该协议的类也需求实现其父类的方法。如果没有父协议,可以不写<>

Objective-C2.0后,protocol添加了两个属性,@required@optional,默认是@required,所以方法1、方法2和方法4都是@required@optional是可选的,@required实现类必须实现的,否则会报错

  • 方法调用

先展示出来:

术语

方法调用(对象car调用run(time,distance)

C#

car.run(time,distance);

Java

car.run(time,distance);

Objective-C

[car run:time :distance];

方法调用时,OC使用的不是.而是[],一层代表一个函数,方法名上面说过了,是“run::”OC中,虽然也说是方法调用,但是其实在Objective-C中,是没有方法调用这个概念的,在OC中叫做消息传递。在OC中方法和类是松耦合的,该类可以在运行时决定怎么处理这个消息。[car run:time :distance]会被转换为objc_msgSend(car,run::,time,distance)是不是跟平时看到的方法一样了。每个类都有一个isa员,它里面有一个方法列表,对应的是方法名和方法地址,以此来达到调用方法

大家只需要知道OC是通过消息传递的方式调用方法的即可。会使用即可

  • super,self:

术语

指向本类实例指针

指向父类实例指针

C#

this

base

Java

this

super

Objective-C

self

super

  • NSObject:

术语

C#

Object

Java

Object

Objective-C

NSObject

  • id:

上面说到isa员,其实id是指向isa的指针。其他语言中没有,是一个指向指针的指针,不需要这么深,你只要知道id是一个可以指向任一类型对象的指针,在概念上,类似Java Object,可以转换为任何数据类型

id name = [[NSString alloc] init];

这里id指向的是NSString类型对象。相当于了【NSString *

记:除了基本类型以外,如Integer,Float等,所有对象类型都是定义指针类型,必须加*,否则报错。

NSString *name = [[NSString alloc] init];

  • nil

类似null

  • Category

不知道JAVAC#有没有类似的概念,据我所知,Objective-C是我接触过的里面第一个

使用Object-C中的分类,是一种编译时的手段,允许我们通过给一个类添加方法来扩充它(但是通过category不能添加新的实例变量),并且我们不需要访问类中的代码就可以做到。具体概念就不说了,直接说实现和对我们的意义影响

当我们需要扩展一个类的时候,按传统方式一般是写一个子类继承它,然后定义子类对象。如果又有一个新功能呢?继续继承,原来定义的实例除非改变为子类类型,否则不能访问新方法。这时候分类出现了

譬如我们已经有一个Car类,方法有run现在我们想添加一个stopping方法

@interfaceCar(motionCar)
{
-(void) stopping;
}
@implementation Car(motionCar)
{
-(void) stopping{
方法体
}
}

可以看出,其实和上面普通类定义区别不大,就是后面多了个【()】,括号中的是分类名,分类文件名一般是【原有类名+类名称

调用的时候如下

Car *car = [[Car alloc] init];
[car run];
[car stopping];

类中的方法就相当于往原类中添加方法。同样,注意点出现了,分类中的方法会影响到原类的所有子类,以及它们的实例对象。分类中的方法优先级高于原类,如果方法名与原类重名,那么就类似覆盖,会影响所有既存功能。所以除非必要,不要命名与原类同名方法。(多个分类出现同名方法,每个分类优先度是等同的,等概率事件

另:分类只能添加新方法,无法添加新的属性

  • 扩展Extension):

扩展和分类长得很像,但是()是空的,但是只是长的像哦,作用完全不同

类的扩展可以添加新的属性和方法,放在原类的.m文件中。用于类的封装,定义类的私有属性和私有方法。方法实现依然在原类的@implementation

.h
@interface Car:NSObject
{
-(void) run;
}
.m
@interface Car()
{
NSString *color;
-(void) stopping;
}
@implementation Car()
{
-(void) run{
方法体
}
-(void) stopping{
方法体
}
}

如上,runpublic方法,stopping是私有方法,外界访问不到,color是新添加的属性,外界通.h是看不到的,这样外部通过头文件看到的只是你想要让别人看到的方法和属性。是苹果所推荐的

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值