【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态(二)

简介: 【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态(二)

2. Key 不存在的情况处理



(1) 情况简介



前提 : KVC 操作时, 如果遇到 既没有 getter setter 方法, 也没有 "_属性值" 或者 "属性值" 成员变量时, KVC 会调用 "setValue : forUndefinedKey :" 和 "valueForUndefinedKey :" 方法, 系统只是定义了两个默认方法, 但是并没有执行实际有意义的内容;





(2) 异常代码示例


示例代码 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@end
@implementation OCPerson
@synthesize name;
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * p = [[OCPerson alloc] init];
  [p setValue : @"Jack" forKey : @"son"];
  [p valueForKey : @"son"];
  }
}


-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m 
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 22:21:58.642 a.out[3611:507] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<OCPerson 0x7fecd0c09610> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key son.'
*** First throw call stack:
(
  0   CoreFoundation                      0x00007fff8e37625c __exceptionPreprocess + 172
  1   libobjc.A.dylib                     0x00007fff8cc74e75 objc_exception_throw + 43
  2   CoreFoundation                      0x00007fff8e375e09 -[NSException raise] + 9
  3   Foundation                          0x00007fff8d83d72e -[NSObject(NSKeyValueCoding) setValue:forKey:] + 389
  4   a.out                               0x000000010e9fae15 main + 117
  5   libdyld.dylib                       0x00007fff8318c5fd start + 1
  6   ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6




(3) 处理 setValue : forKey 异常代码示例


代码示例 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@end
@implementation OCPerson
@synthesize name;
-(void) setValue : (id) value forUndefinedKey : (id) key
{
  NSLog(@"You want set value %@ to %@ key", value, key);
}
-(void) valueForUndefinedKey : (id) key
{
  NSLog(@"You want get the value of %@ key", key);
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * p = [[OCPerson alloc] init];
  [p setValue : @"Jack" forKey : @"son"];
  [p valueForKey : @"son"];
  }
}



-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m 
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 22:27:17.699 a.out[3623:507] You want set value Jack to son key
2015-09-30 22:27:17.703 a.out[3623:507] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<OCPerson 0x7fd162408cf0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key son.'
*** First throw call stack:
(
  0   CoreFoundation                      0x00007fff8e37625c __exceptionPreprocess + 172
  1   libobjc.A.dylib                     0x00007fff8cc74e75 objc_exception_throw + 43
  2   CoreFoundation                      0x00007fff8e375e09 -[NSException raise] + 9
  3   Foundation                          0x00007fff8d90e14e -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 235
  4   Foundation                          0x00007fff8d825466 -[NSObject(NSKeyValueCoding) valueForKey:] + 381
  5   a.out                               0x00000001049d6ddc main + 140
  6   libdyld.dylib                       0x00007fff8318c5fd start + 1
  7   ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6



(4) 处理 valueForKey 异常代码示例


代码示例 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@end
@implementation OCPerson
@synthesize name;
-(void) setValue : (id) value forUndefinedKey : (id) key
{
  NSLog(@"You want set value %@ to %@ key", value, key);
}
-(id) valueForUndefinedKey : (id) key
{
  NSLog(@"You want get the value of %@ key", key);
  return nil;
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * p = [[OCPerson alloc] init];
  [p valueForKey : @"son"];
  }
}

-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 22:33:43.557 a.out[3652:507] You want get the value of son key





2. 处理 nil 值



(1) 情况简介


问题引入 : 使用 KVC 设置对象属性, 如果属性是指针类型, 设置 nil 值完全正确, 如果为 基本类型 int short 类型设置了 nil 会出现异常;


-- 异常信息 : 为基本类型设置 nil 会爆出 NSInvalidArgumentException 异常, int 类型不能接受 nil 值;


-- "setNilValueForKey :" 方法 : 为成员变量设置 nil 时, 如果该成员变量不接受 nil 值, 系统会自动执行 setNilValueForKey 方法;


-- 定制 "setNilValueForKey :" 方法 : 重写了该方法之后, 如果再试图给 不接受 nil 值的变量赋值 nil, 就会自动调用该方法;





(2) 异常示例代码



示例代码 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@property (assign, nonatomic) int age;
@end
@implementation OCPerson
@synthesize name;
@synthesize age;
-(void) setValue : (id) value forUndefinedKey : (id) key
{
  NSLog(@"You want set value %@ to %@ key", value, key);
}
-(id) valueForUndefinedKey : (id) key
{
  NSLog(@"You want get the value of %@ key", key);
  return nil;
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * p = [[OCPerson alloc] init];
  [p setValue : nil forKey : @"age"];
  NSLog(@"age : %@", [p valueForKey : @"age"]);
  }
}


-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 23:11:56.652 a.out[3920:507] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<OCPerson 0x7ffe0b409870> setNilValueForKey]: could not set nil as the value for the key age.'
*** First throw call stack:
(
  0   CoreFoundation                      0x00007fff8e37625c __exceptionPreprocess + 172
  1   libobjc.A.dylib                     0x00007fff8cc74e75 objc_exception_throw + 43
  2   CoreFoundation                      0x00007fff8e37610c +[NSException raise:format:] + 204
  3   Foundation                          0x00007fff8d90e2a7 -[NSObject(NSKeyValueCoding) setNilValueForKey:] + 73
  4   Foundation                          0x00007fff8d83d72e -[NSObject(NSKeyValueCoding) setValue:forKey:] + 389
  5   a.out                               0x000000010da0ad38 main + 120
  6   libdyld.dylib                       0x00007fff8318c5fd start + 1
  7   ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6




(3) 异常处理示例代码


异常处理示例代码 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@property (assign, nonatomic) int age;
@end
@implementation OCPerson
@synthesize name;
@synthesize age;
-(void) setValue : (id) value forUndefinedKey : (id) key
{
  NSLog(@"You want set value %@ to %@ key", value, key);
}
-(id) valueForUndefinedKey : (id) key
{
  NSLog(@"You want get the value of %@ key", key);
  return nil;
}
-(void) setNilValueForKey : (id) key
{
  if([key isEqualToString : @"age"])
  {
  age = 0;
  }else
  {
  [super setNilValueForKey : key];
  }
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * p = [[OCPerson alloc] init];
  [p setValue : nil forKey : @"age"];
  NSLog(@"age : %@", [p valueForKey : @"age"]);
  }
}



-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 23:19:27.980 a.out[3934:507] age : 0





3. Key 路径



(1) 复合属性


复合属性 : 在类 OCStudent 中 定义了 OCPerson 成员变量, 如果我们想要访问 OCPerson 中得 name 成员变量, 就需要先访问 OCPerson 成员变量, 再访问 name 成员变量;




Key 路径操作方法 :


-- " setValue : forKeyPath : " 方法 : 根据 key 路径设置属性值;


-- " valueForKeyPath : " 方法 :  根据 key 路径获取属性值;




KVC 优缺点 :


-- 缺点 : KVC 操作对象性能要比使用 getter 和 setter 方法要差;


-- 优点 : KVC 使用会使程序更加简洁, 适合提炼通用代码, 具有极高的灵活性;







(2) Key 路径示例代码




示例代码 :


-- OCPerson.h :



/*************************************************************************
    > File Name: OCPerson.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 23:39:06 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@property (assign, nonatomic) int age;
@end

-- OCPerson.m :


/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import "OCPerson.h"
@implementation OCPerson
@synthesize name;
@synthesize age;
-(void) setValue : (id) value forUndefinedKey : (id) key
{
  NSLog(@"You want set value %@ to %@ key", value, key);
}
-(id) valueForUndefinedKey : (id) key
{
  NSLog(@"You want get the value of %@ key", key);
  return nil;
}
-(void) setNilValueForKey : (id) key
{
  if([key isEqualToString : @"age"])
  {
  age = 0;
  }else
  {
  [super setNilValueForKey : key];
  }
}

@end



-- OCOrder.h :


/*************************************************************************
    > File Name: OCOrder.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 23:37:51 2015
 ************************************************************************/
#import "OCPerson.h"
@interface OCOrder : NSObject
@property (nonatomic, strong) OCPerson * person;
@end
-- OCOrder.m : 
/*************************************************************************
    > File Name: OCOrder.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 23:43:08 2015
 ************************************************************************/
#import "OCOrder.h"
@implementation OCOrder
@synthesize person;
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCOrder * order = [[OCOrder alloc] init];
  OCPerson * p = [[OCPerson alloc] init];
  [order setValue : p forKey : @"person"];
  [order setValue : @"Tom" forKeyPath : @"person.name"];
  NSLog(@"name : %@", [order valueForKeyPath : @"person.name"]);
  }
}


-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m OCOrder.m 
octopus-2:oc_object octopus$ ./a.out 
2015-09-30 23:56:44.338 a.out[4031:507] name : Tom








五. 键值监听 (KVO)




1. KVO 简介





IOS 需求 :


-- 数据模型组件 : 负责维护应用程序的状态数据;


-- 视图组件 : 负责显示数据模型组件内部的状态数据;


-- 需求 : 数据模型组件数据发生变化时, 视图组件能动态更新;




KVO (Key Value Observing) 键值监听 :


-- 适用前提 : 只要是 NSObject 子类就可以使用 KVO;


-- 注册监听器用于监听 key 路径 : "addObserver : forKeyPath : options : context";


-- 为 Key 路径删除指定监听器 : "removeObserver : forKeyPath :" 或者 "removeObserver : forKeyPath :";


-- 回调 : 数据发生变化时, 会回调 "observerValueForKeyPath : ofObject : change : context" 方法;




KVO 编程步骤 :


-- 注册监听器 : 为被监听对象注册监听器, 使用 "addObserver : forKeyPath : options : context";


-- 重写监听器方法 : 重写 "observeValueForKeyPath : ofObject : change : contex : " 方法;







2. KVO 代码示例




KVO 代码示例 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, weak) NSString * name;
@property (nonatomic, assign) int age;
@end
@implementation OCPerson
@synthesize name;
@synthesize age;
- (void) setName : (NSString *) str
{
  self->name = str;
  [self addObserver : self forKeyPath : @"name" options : NSKeyValueObservingOptionNew context : nil];
}
- (void) setAge : (int) old
{
  self->age = old;
  [self addObserver : self forKeyPath : @"age" options : NSKeyValueObservingOptionNew context : nil];
}
- (void) observeValueForKeyPath : (NSString *) keyPath 
        ofObject : (id) object
       change : (NSDictionary *) change
      context : (void *) context
{
  NSLog(@"keyPath : %@, object : %@, change : %@", keyPath, object, [change objectForKey : @"new"]);
}
- (void) dealloc
{
  NSLog(@"dealloc callback");
  [self removeObserver : self forKeyPath : @"name"];
  [self removeObserver : self forKeyPath : @"age"];
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * person = [[OCPerson alloc] init];
  person.age = 20;
  person.name = @"Tom";
  person.age = 18;
  person.name = @"Jerry";
  [person removeObserver : person forKeyPath : @"name"];
  [person removeObserver : person forKeyPath : @"age"];
  }
}

-- 执行结果 :


bogon:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m
bogon:oc_object octopus$ ./a.out 
2015-10-01 20:36:39.722 a.out[734:507] keyPath : age, object : <OCPerson: 0x7fac8a4042f0>, change : 18
2015-10-01 20:36:39.724 a.out[734:507] keyPath : name, object : <OCPerson: 0x7fac8a4042f0>, change : Jerry
2015-10-01 20:36:39.724 a.out[734:507] dealloc callback






六. Object-C 对象初始化





1. 实例空间分配过程




创建对象语法 : [[类名 alloc] init] 语法, [类名 new] 语法, 每次创建对象都要调用该对象的 alloc 方法为对象分配内存空间;


-- alloc 方法 : alloc 方法 是在 NSObject 中定义的, 所有的 OC 对象都是 NSObject 的子类, 所有的类都可以调用 alloc 方法为所有的实例变量分配内存;


-- init 方法 : 来自 NSObject 中定义, 所有的对象调用 init 方法进行初始化, 将每个成员变量内存空间赋值为 0, 所有的整型变量所在空间都重置为 0, 浮点型变量 0.0, BOOL 型变量 NO, 指针型 nil;


-- 注意 : 使用 [类名 init] 创建的对象也可以执行, 但是没有进行 init 初始化, 可能出现未知结果;







2. 初始化方法 与 对象初始化




(1) 重写初始化方法




初始化方法种类 :


-- 默认初始化 : NSObject 提供的 默认的 init 方法为所有成员变量赋值 0 初始值;


-- 常用初始化 : 重写 NSObject 的 init 方法, 可以加入任意的自定义初始化过程;



- (id) init
{
  if(self = [super init])
  {
  self.name = @"Tom";
  self.age = 18;
  self.address = @"DC";
  }
  return self;
}



-- 默认初始化调用 :


OCPerson * person1 = [[OCPerson alloc] init];


-- 多个初始化方法 : 还可以自定义 initXxx 方法, 可以根据参数执行自定义初始化;



- (id) initWithHobby : (NSString *) hobby_value
{
  if(self = [super init])
  {
  self.name = @"Jerry";
  self.age = 20;
  self.address = @"ST";
  self.hobby = hobby_value;;
  }
  return self;
}


-- 其它初始化方法调用 :


OCPerson * person2 = [[OCPerson alloc] initWithHobby : @"football"];







(2) 初始化方法示例代码




示例代码 :



/*************************************************************************
    > File Name: OCPerson.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 三  9/30 09:10:09 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCPerson : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString * address;
@property (nonatomic, copy) NSString * hobby;
- (id) initWithHobby : (NSString *) hobby_value;
@end
@implementation OCPerson
@synthesize name;
@synthesize age;
@synthesize address;
@synthesize hobby;
- (id) init
{
  if(self = [super init])
  {
  self.name = @"Tom";
  self.age = 18;
  self.address = @"DC";
  }
  return self;
}
- (id) initWithHobby : (NSString *) hobby_value
{
  if(self = [super init])
  {
  self.name = @"Jerry";
  self.age = 20;
  self.address = @"ST";
  self.hobby = hobby_value;;
  }
  return self;
}
@end
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCPerson * person1 = [[OCPerson alloc] init];
  NSLog(@"name : %@, age : %d, address : %@, hobby : %@", person1.name, person1.age, person1.address, person1.hobby);
  OCPerson * person2 = [[OCPerson alloc] initWithHobby : @"football"];
  NSLog(@"name : %@, age : %d, address : %@, hobby : %@", person2.name, person2.age, person2.address, person2.hobby);
  }
}




-- 执行结果 :



bogon:oc_object octopus$ clang -fobjc-arc -framework Foundation OCPerson.m
bogon:oc_object octopus$ ./a.out 
2015-10-01 21:47:06.409 a.out[832:507] name : Tom, age : 18, address : DC, hobby : (null)
2015-10-01 21:47:06.410 a.out[832:507] name : Jerry, age : 20, address : ST, hobby : football






七. 类的继承




1. OC 类继承简介





继承简介 :

-- OC 继承 : OC 继承是单继承, 一个子类只能有一个父类, 这点与 Java 相同;

-- 子类继承父类格式 : 只需要在接口部分声明类时, 在类名后面加上 ": SuperClass" 即可;


@interface SubClass : SuperClass
{
  //成员变量
}
//方法
@end

-- 子类收获 : 子类扩展父类时, 子类可以得到父类的 全部方法 和 全部成员变量;



super 关键字 :

-- 作用 : 在子类方法调用父类被覆盖的实例方法, 该关键字用于限定对象调用其从父类获得的属性 和 方法;

-- 注意 : super 关键字不能出现在 类方法中, 因为类方法执行是不依靠对象的;

-- self 对比 : self 也不能出现在类方法中;






2. OC 类继承 源码示例




源码示例 :


-- OCAnimal.h : 父类的接口头文件, 定义了两个属性;
/*************************************************************************
    > File Name: OCAnimal.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:21:19 2015
 ************************************************************************/
#import <Foundation/Foundation.h>
@interface OCAnimal : NSObject
@property (nonatomic, copy) NSString * name;
@property (assign, nonatomic) int age;
-(void) info;
@end
-- OCAnimal.m : 父类的实现类, 声明了接口中得两个属性, 实现了一个方法;
/*************************************************************************
    > File Name: OCAnimal.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:23:37 2015
 ************************************************************************/
#import "OCAnimal.h"
@implementation OCAnimal
@synthesize name;
@synthesize age;
- (void) info
{
  NSLog(@"name : %@, age : %d", name, age);
}
@end
-- OCCat.h : 子类的接口头文件, 定义了新的成员变量 和 方法;
/*************************************************************************
    > File Name: OCCat.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:28:22 2015
 ************************************************************************/
#import "OCAnimal.h"
@interface OCCat : OCAnimal
@property (nonatomic, copy) NSString * color;
- (void) purr;
@end
-- OCCat.m : 子类的实现, 此外还 重写了 父类 info 方法;
/*************************************************************************
    > File Name: OCCat.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:34:05 2015
 ************************************************************************/
#import "OCCat.h"
@implementation OCCat
@synthesize color;
- (void) info
{
  [super info];
  NSLog(@"color : %@", color);
}
- (void) purr
{
  NSLog(@"%@ 喵喵", super.name);
}
@end
-- OCCatTest.m : 子类测试类;
/*************************************************************************
    > File Name: OCCatTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:37:16 2015
 ************************************************************************/
#import "OCCat.h"
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  OCCat * cat = [[OCCat alloc] init];
  cat.name = @"小花";
  cat.age = 18;
  cat.color = @"red";
  [cat info];
  [cat purr];
  }
}



-- 执行结果 :


octopus-2:oc_object octopus$ clang -fobjc-arc -framework Foundation OCAnimal.m OCCat.m OCCatTest.m 
octopus-2:oc_object octopus$ ./a.out 
2015-10-02 13:43:08.575 a.out[696:507] name : 小花, age : 18
2015-10-02 13:43:08.576 a.out[696:507] color : red
2015-10-02 13:43:08.577 a.out[696:507] 小花 喵喵








八. OC 多态





1. OC 类继承简介




(1) 编译运行时类型



指针变量类型 : 如果编译时与运行时类型不同, 就会产生多态;

-- 编译时类型 : 由声明该变量时使用的类型决定;

-- 运行时类型 : 由实际赋值给该变量的类型决定;




(2) 赋值多态



赋值多态 : 子类可以在任意位置替换父类 (里氏替换);

-- 多态出现 : 子类赋值给父类时, 编译时类型是父类, 运行时类型是子类;

-- 调用重写方法 : 调用子类重写父类的方法时, 执行的是父类方法;

-- 多态 : 相同类型的变量调用同一个方法, 会出现不同的特征, 这就是多态;



(3) 指针变量强制类型转换



指针变量强制类型转换 :

-- 问题出现 : 将子类赋值给父类类型对象时, 就不能再使用父类对象调用子类的方法和属性, 此时需要将父类类型对象强制转换为子类类型对象;

-- 类型转换方法 : "(类型名称 *) 对象名",

-- 将父类转为子类 : 这种强转只是改变指针变量的编译时类型, 变量指向的实际类型不会发生改变;

-- 判断类型 : 转换时需要进行类型判断对象类型, 否则容易出错;



(4) 判断指针变量的实际类型



判断指针变量实际类型 :

-- 判断对象是否是 clazz 类对象 : "- (BOOL) isMemberOfClass : clazz";

-- 判断对象是否是 clazz 类 或 子类 实例 : "- (BOOL) isKindOfClass : clazz :";

-- 判断当前是否是 clazz 子类 : "+ (BOOL) isSubclassOfClass : clazz :"







2. 多态代码示例


代码示例 :


-- OCCatTest.m : 该类与上面的 OCAnimal.h, OCAnimal.m, OCCat.h, OCCat.m 四个类同时使用;
/*************************************************************************
    > File Name: OCCatTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 五 10/ 2 13:37:16 2015
 ************************************************************************/
#import "OCCat.h"
int main(int argc, char * argv[])
{
  @autoreleasepool
  {
  //多态示例
  OCAnimal * animal = [[OCAnimal alloc]init];
  animal.name = @"Jerry";
  animal.age = 18;
  NSLog(@"animal.name : %@, animal.age : %d", animal.name, animal.age);
  OCCat * cat = [[OCCat alloc]init];
  cat.name = @"Tom";
  cat.age = 20;
  NSLog(@"cat.name : %@, cat.age : %d", cat.name, cat.age);
  OCAnimal * father = [[OCCat alloc]init];
  father.name = @"Kit";
  father.age = 25;;
  NSLog(@"father.name : %@, father.age : %d", father.name, father.age);
  //[father purr]; //父类不能调用子类方法, 编译类型与方法不符, 编译不通过
  /*
   * 类型转换示例
   * 如果使用 [father purr] 编译时就会报错
   * 将 father 强转为 OCCat * 类型, 编译运行就没问题了, 如下
   */
  [(OCCat *)father purr];
  BOOL isAnimalObject = [animal isKindOfClass : [NSObject class]];
  NSLog(@"isAnimalObject : %d", isAnimalObject);
  }
}


-- 执行结果 :


localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCAnimal.m OCCat.m OCCatTest.m 
localhost:oc_object octopus$ ./a.out 
2015-10-03 07:51:07.415 a.out[712:507] animal.name : Jerry, animal.age : 18
2015-10-03 07:51:07.417 a.out[712:507] cat.name : Tom, cat.age : 20
2015-10-03 07:51:07.417 a.out[712:507] father.name : Kit, father.age : 25
2015-10-03 07:51:07.417 a.out[712:507] Kit 喵喵
2015-10-03 07:51:07.418 a.out[712:507] isAnimalObject : 1
目录
相关文章
|
3月前
|
iOS开发 开发者
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
233 67
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
|
2月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
86 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
1月前
|
缓存 安全 数据处理
Objective-C开发:从HTTP请求到文件存储的实战
Objective-C开发:从HTTP请求到文件存储的实战
|
4月前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
198 66
|
2月前
|
人工智能 程序员 API
iOS|记一名 iOS 开发新手的前两次 App 审核经历
啥,这玩意也有新手保护期?
46 0
|
4月前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
296 11
|
4月前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
224 3
|
4月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
5月前
|
存储 前端开发 Swift
探索iOS开发:从新手到专家的旅程
本文将带您领略iOS开发的奇妙之旅,从基础概念的理解到高级技巧的掌握,逐步深入iOS的世界。文章不仅分享技术知识,还鼓励读者在编程之路上保持好奇心和创新精神,实现个人成长与技术突破。
|
5月前
|
安全 IDE Swift
探索iOS开发之旅:从初学者到专家
在这篇文章中,我们将一起踏上iOS开发的旅程,从基础概念的理解到深入掌握核心技术。无论你是编程新手还是希望提升技能的开发者,这里都有你需要的指南和启示。我们将通过实际案例和代码示例,展示如何构建一个功能齐全的iOS应用。准备好了吗?让我们一起开始吧!
下一篇
oss创建bucket