Objective-c 学习笔记(三)

来源:互联网 发布:关于网络拍卖司法解释 编辑:程序博客网 时间:2024/06/01 23:32
1.分类:(category)
分类:提供了一种简单的方式,可以将类的定义模块化到相关方法的组或分类中,
提供了扩展现有类定义的简便方法,并且不必访问类的源代码,也无需创建子类。
分类的使用场景:
  • 想给一个类添加一些新方法
  • 一个大项目中,你为一个类编写处理文件系统的方法,其他成员负责创建和初始化类的实例、执行操作
  • 你已经知道如何使用库中的类,如Foundation框架的数组类,名为NSArray,但希望能实现一个或多个方法。(可以编写NSArray的子类,但是存在更简单的方法)
分类的定义:
原类
#import <Foundation/Foundation.h>
@interface Fraction:NSObject
@property int numerator, ...
    
分类MathOps
#import “Fraction.h"
@interface Fraction (MathOps) //告诉编译器正在为Fraction定义新的分类
-(Fraction *) add: (Fraction *) f;
-(Fraction *) mul: (Fraction *) f;
-(Fraction *) sub: (Fraction *) f;
-(Fraction *) div: (Fraction *) f;
@end
分类中不能再列出原类的实例变量。
按照惯例,作为分类的.h和.m文件的基本名称是由类的名称紧接分类的名称。
如接口部分FractionMathOps.h 实现部分FractionMathOps.m。
一些人使用+来分隔如Fraction+MathOps.h

2. 类的扩展
  • 创建一个分类,但是在()之间不指定名字,成为“类的扩展”
  • 普通的类的分类不允许定义附加的实例变量,但是在类的扩展中可以定义。
  • 未命名分类中声明的方法需要在主实现区域实现,不允许在分类的实现区域中实现。
  • 如果没有实现未命名分类的接口列出的全部方法,编译器会警告。
  • 未命名分类的方法都是私有的,如果需要写一个类,数据和方法仅供这个类本身使用,未命名分类比较合适
  • 分类可以覆盖该类中的另一个方法,但并不建议。确实需要覆盖,可以选择子类
  • 通过分类来添加方法,不仅会影响这个类,还会影响他的子类
@interface GraphicObject()
@proper int uniqueID;

-(void) doStuffwithUniqueID: (int) theID;
@end

//-------------------------
@implementation GraphicObject
@Synthesize uniqueID;
-(void) doStuffWithUniqueID: (int) myID{
   self.uniqueID = myID;
   ...
}
@end
3. 协议和代理
  • 协议是多个类共享的一个方法列表,协议中列出的方法没有对应的实现。
  • 使用@protocol执行定义协议
  • 比如要实现copy方法,需采用NSCopying协议
  • 如果要采用NSCopying协议,必须实现名为copyWithZone的方法。
  • 同时@interface行的尖括号<>来列出协议名称。@interface AddressBook : NSObject <NSCopying>
  • 可以实现多项协议 @interface AddressBook : NSObject <NSCopying, NSCoding>
  • 可以通过@optional来标明可选的方法
  • @protocol Drawing
    -(void) paint;
    -(void) erase;
    @optional
    -(void) outling;
    @end
  • 判断一个对象是否遵循某项协议conformsToProtocol
  • id currentObject;
    if{[currentObject conformsToProtocol : @protocol (Drawing)] = YES){...}
    @protocol用于获取一个协议名称,并产生一个Protocol对象。
  • 判断是否实现了可选的optional方法outline
  • if( [ currentObject respondsToSelector : @selector (outline) ] == YES)
      [currentObject outline];
  • 定义一项协议时,可以扩展现有协议的定义,如@protocol Drawing3D <Drawing>
  • 分类也可以采用一项协议 @interface Fraction (Stuff) <NSCopying, NSCoding>

代理
定义了协议的类可以看做是将协议定义的方法代理给了实现他们的类。
这样类的定义可以更通用,具体的动作由代理类来承担,来做具体的动作。
Cocoa和IOS非常依赖代理的概念,如:
建一个表格,会用到UITableView类。
代理定义了一个UITableViewDataSource协议,用来提供标题是什么,含多少行
如需知道多少行,就跳类中实现协议的相关方法。
UITableView还定义了一些其他方法,比如选中行后的动作。

非正式协议 informal
实际上市一个分类,列出了一组方法但是没有实现它。有时,也成为抽象协议abstract协议

4. 合成对象 Composite

预处理程序
1. #define语句
给符号名称指定程序常量  
#define TRUE 1    //注意没有等号,结尾么有分号(不能有分号,替换后会出错)
#define FALSE 0
利于在文本编辑器中进行搜索和替换。
预定义的值本身可以引用另一个预定义的值
#define IS_LEAP_YEAR(y)  y % 4 == 0 && y % 100 != 0 \   (注意,用\换行)
                || y % 400 = 0
#define SQUARE(x) x*x
-----------------------------------------------
陷阱:这种定义下y = SQUARE(V+1)会出现什么?  应该是 y=v+1*v+1,而不是(v+1)(v+1)
因为:预处理程序对宏定义的参数实行的是文本替换。
为解决这个问题,需要在SQUARE的宏定义中加入括号
#define SQUARE(x) ( (x) * (x) )
-----------------------------------------------
以下的宏允许方便的根据Fraction动态创建新分数
#define MakeFract(x,y) ([[Fraction alloc] initWith: x over: y])
然后 myFract = MakeFract(1,3); 即可
-----------------------------------------------

2. #import 语句
可以将定义的宏收集在一个单独的文件中,然后用#import语句包含进来。常以h结尾,称为头文件或包含文件。
#import "metric.h" 把数学相关的宏都放在这个头文件中了

-----------------------------------------------
3. 条件编译
长用于创建在不同计算机系统上编译程序。
#ifdef #endif #else #ifndef 语句
举个例子:假设前面已经定义了符号IPAD
#ifdef IPAD
# define kImageFile @"barnHD.png"
#else
# define kImageFile @"barn.png"
#endif

-----------------------------------------------
使用XCode,通过 Build Setting可以添加新的预定义名称并指定他们的值。
#ifndef 如果指定的符号没有定义。。。
#undef 语句,一些情况下,可能需要使一些已经定义的名称成为未定义的。#undef IPAD消除对IPAD的定义

应用,不如#ifdef DEBUG
-----------------------------------------------


0 0
原创粉丝点击