Objective-C 学习记录

Objective-C下的类定义不同于之前学过的C, C++, 他有着自己的一些标志:

1 @interface NewClassName : ParentClassName
2 {
3      memberDeclarations;
4 }
5 methodDeclarations;
6 @end

结构还是比较清楚. 包围在大括号之内的就是实例变量(instance variables).

Objective-C用来区分实例方法和类方法的手段就是方法定义前的标志, "-"(minus)表示是实例方法, "+"(plu)表示是类方法.

 方法定义的结构如下:

- (void) methodName : (int) arg;

 需要注意的地方是: 在方法名后如果跟着一个分号, 表示后面有参数,  否则就表示没有参数传进来.

 定义完了一个类之后, 就要具体的实现他了. 就好像是C++中在.h文件中定义完类, 然后就去.cpp中完成具体的实现. 只不过这里要将.cpp换成是.m罢了.

1 @implementation NewClassName : ParentClassName
2     methodDefinitions
3 @end

还要注意一点, 不同于其他的语言, 比如我们经常使用的C, C++, Java, Python等, 习惯于使用"."来表示方法调用,  Objective-C中的方法调用形式是使用中括号"[]":

[ClassOrInstance method]

 这个可能是学习Objective-C中比较别扭的一个地方吧.

Objective-C中有一种类型称为:id.

被声明成该类型的变量, 可以用来存储任何类型的对象, 感觉非常像C, C++中的空指针.

方法声明中, 如果不指定范围类型和参数类型, 默认就是id.

+methodName;

 id主要是用在多态和动态绑定上.

既然id可以用来表示任何类型的数据,为什么在编写代码的时候不将所有的变量类型都声明为id类型呢?有这么几个原因:

  1. 在变量声明的时候,如果指定了具体类型,比如int,float, ClassName等,称为静态类型声明。这样,编译器在编译阶段就能够了解到变量类型,从而更好地进行编译优化等工作。
  2. 如果使用id作为变量类型,那么类型检查,方法查找等工作就是在运行期进行的。而这样,如果程序中存在错误,也只能在运行时发现。一旦投入到生产环境,将是非常可怕的。
  3. 最简单的原因就是为了代码的可读性,声明成id类型当然不如声明成具体类型直观了。

Objective-C关于面向对象这部分,多了几个概念,不同于之前学过的C++,有必要在这里详细说明一下。

一、Category:

总的来说,category就是对已经存在的类进行一些修改,方法的重载(还有些不同于继承),添加新方法等。

基本语法如下:

@interface ClassName (CategoryName)
methodDeclaration;
@end

@implementation ClassName (CategoryName)
methodDefinition;
@end

 这样,ClassName在CategoryName下就有了新的方法,也就是说,对原有的ClassName进行了扩充。

但是,这里还有几点需要注意:

  1. 虽然category可以访问类的实例变量,去不能创建新的实例变量,如果要创新的实例变量,请使用继承;
  2. 在category中,不提倡对原有方法进行重载。原因非常简单,在category中进行重载,无法对原方法进行访问,而继承中可以使用super。如果真的需要对原方法进行重载,请考虑继承;
  3. 一个类可以定义多个category,但是如果不同category中存在相同方法,编译器无法决定使用哪个category;
  4. 在定义category时,我们可以仅仅给出方法定义,而不需要给出具体的实现。这在程序增量开发时是非常有帮助的;
  5. category是可以被继承的。在某个父类中定义了category,那么他所有的子类都具有该category;

 

二、Posing:

通过postAs方法,可以将一个类型“假扮”成另一种类型。

[ClassA postAs: ClassB];

当有消息发送给ClassB的实例时,那么就会调用ClassA中的相应方法(当然,该方法必须存在)。这样,ClassA的就成功的模拟了ClassB。

三、Protocol:

Protocol有点Java里interface的味道。定义了一组方法,而不提供具体实现。只有那些“遵守”(conform to)或“采用”(adopt)了这些Protocol的类来给出自己的实现。

Protocol的语法如下:

@protocol ProtocolName
methodDeclaration;
@end

而在类声明时,语法如下:

@interface ClassName : ParentClassName <ProtocolName1, ...>

一个类可以采用多个Protocol。

Protocol也可以采用别的Protocol:

@protocol ProtocolName1 <ProtocolName2, ...>

当然,category也可以在定义时指定采用的Protocol:

@interface ClassName (CategoryName) <ProtocolName2, ...>

 

在Objective-C里要注意一点, 文件依赖一般都是通过import来导入的, 如此一来, 在工程较大, 文件定义较多的时候, 会需要在编译阶段消耗很多时间. 比如A.h import了 B.h, 一旦A文件有了改动, 那么B也会在编译时重新进行编译. 如果有上百个文件相互一来, 造成cascade of changes, 那么编译过程可想而知.

大多时候, 我们只想引用一个类, 比如集成或者复合. 这个时候最好就是使用

@class ClassName

这个关键字, 他会告诉编译器, hey dude, 我只想引用这个class, 不想知道他的实现细节, please calm down.

还有一种情况, 循环引用, 如果A引用了B, B又引用了A, 如果使用import,编译器就会出错. 而@class会让两者和平共处.

但是, 在继承的时候, 还是需要使用import, 为什么呢? 很简单, 编译器需要知道继承的父类的具体信息. 有那些变量, 方法等等. 如果这个时候使用@class, 就不合时宜了.

时间: 2024-08-04 07:10:04

Objective-C 学习记录的相关文章

kubernetes学习记录(7)——弹性伸缩与滚动升级

kubernetes学习记录(7)--弹性伸缩与滚动升级. 弹性伸缩 弹性伸缩是指适应负载变化,以弹性可伸缩的方式提供资源. Pod的弹性伸缩就是修改Replication Controller的Pod副本数.可以通过Kubectl scale命令实现. 创建Replication Controller test-rc.yaml apiVersion: v1 kind: ReplicationController metadata: name: test-rc spec: replicas: 2

js和jquery中循环的退出和继续学习记录_javascript技巧

作为水货,就是学会了1+1=3也要记录一下!错了,是2 学习记录: js中的 for(var i=1;i<5;i++){ if(i==3){ break; // 使用break,弹出2次提示分别为1,2:如果使用continue,则会弹出3次,分别是1,2,4 } alert(i); } 循环,退出循环,使用break:退出当前循环继续下一个循环,使用continue jquery中的each()方法中要实现break,使用return false:continue,使用return true

V4L2学习记录【转】

转自:http://blog.chinaunix.net/uid-30254565-id-5637600.html 4L2学习记录                                                                                                                                    这个还没有分析完,先在这放着,防止电脑坏掉丢了,以后再完善 V4L2的全称是video for linux

zookeeper学习记录三(session,watcher,persit机制)

背景 继续前面的zookeeper学习的专题,这次主要是结合项目中遇到的一些问题,进一步学习了下zookeeper的一些内部机制.   针对以下几个问题: 1. zk是否可以保证watcher事件不丢失? 2. zk的EPHEMERAL节点的自动过期时间?  3. zk的如何保证节点数据不丢失?   如果你已经非常清楚这以上的几个问题,看官们可以不用往下看了.  persit机制 zookeeper中的persit机制主要是通过本地disk进行持久化,在本地disk上会有个memory数据对象保

Android NDK学习记录

游戏项目开始转向Cocos2d-x来开发.需要用什么NDK.cygwin.硬着头皮开始学习. 下载NDK,最新版r7.解压到D:\Develop,地址如下:http://dl.google.com/android/ndk/android-ndk-r7-windows.zip 项目的native代码放在 <project>/jni/... 创建 <project>/jni/Android.mk 描述navive代码. 编译native代码: cd <project> &l

ViewPager适配器学习记录( pageAdapter和FragmentPagerAdapter/FragmentStatePagerAdapter))

1.概述 ViewPager,顾名思义实现控件的滚动功能,是Support-v4的包中类,使用前要先导包.使用的时候跟listView有点相似,需要设置对应的适配器,通常有俩大类 [pageAdapter] [FragmentPagerAdapter/FragmentStatePagerAdapter] fragment有着自己的生命周期,谷歌官方也推荐使用ViewPage+fragment的形式,一般简单的也可以使用ViewPage+pageAdapter形式 这里用这俩种适配器来搭个框架学习

SQL学习记录

======================================================================================== ======================================================================================== 2017/09/11 一.创建表格 CREATE TABLE db(col1 textType, col2 textType, ....); P

CMake学习记录--list(列表操作命令)

CMake是一个跨平台的工程管理工具,能方便的把工程转换为vs各个版本.Borland Makefiles.MSSYS Makefiles.NMake Makefiles等工程,对于经常在不同IDE下使用管理同一个工程提供了很大的便利.自己把使用过程中的点点滴滴记录下来. list 列表操作命令. 1. list(LENGTH <list> <output variable>) 2. list(GET <list> <element index> [<

学习记录ES6反射内置对象Proxy与Reflect

工作中遇见了一个这样的需求:网页预览视频文件(格式有两种mp4与wmv)时,mp4格式的采用浏览器自带的video标签进行播放,wmv格式的由于浏览器不支持直接播放,则需要调用定制的wmvH5播放器来播放. 经调研发现wmvH5播放器实际上也是采用video标签进行播放的,只不过是加载.播放.暂停.定位播放等核心功能进行了特殊定制,其他如音量控制.播放状态等都是video自带的. 为了减少冗余代码,统一调用接口,我首先想到的是JS的对象继承.方法覆写,可没能实现.后来通过翻阅MDN的JavaSc