目录

Objective-C_07.面向对象—多态

一、基本概念

多态在代码中的体现,即为多种形态,必须要有继承,没有继承就没有多态。

在使用多态是,会进行动态检测,以调用真实的对象方法。

多态在代码中的体现即父类指针指向子类对象。

Animal类的声明

1
2
3
4
5
@interface Animal : NSObject

// Animal 类中声明一个 eat 的对象方法
- (void)eat;
@end

Animal类的实现

1
2
3
4
5
6
7
8
@implementation Animal

- (void)eat
{
    NSLog(@"动物吃东西!");
}

@end

Dog类继承自Animal类

1
2
3
4
5
6
7
8
// Dog 类继承自Animal类,拥有了 Animal 类中的所有属性和方法
@interface Dog : Animal

// 在子类中声明了弗雷已经有的 eat 方法,这称之为方法的重写

- (void)eat;

@end

Dog类的实现

1
2
3
4
5
6
7
8
@implementation Dog

- (void)eat
{
    NSLog(@"狗吃东西!");
}

@end

测试程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Dog 类型的指针指向 Dog 类型的对象
  Dog *dog = [[Dog alloc] init];

  // Dog 类对象调用对象方法
  [dog eat];

  // 多态
  // 父类指针指向子类对象
  Animal *a = [[Dog alloc] init];

  // 请问这里调用的是哪个方法?
  [a eat];
  // 动态监测-调用方法时会检测对象的真实类型

  // Animal类型的指针指向Animal类型的对象
  Animal *a1 = [[Animal alloc] init];
  [a1 eat];

  // 下面都是多态的体现
  NSObject *n = [[Dog alloc] init];
  // [n eat]; 不能这样调用

  NSObject *n1 = [[Animal alloc] init];


  // 打印结果
  2016-07-12 19:55:05.783 test[70257:11992740] 狗吃东西!
  2016-07-12 19:55:05.783 test[70257:11992740] 狗吃东西!
  2016-07-12 19:55:05.783 test[70257:11992740] 动物吃东西!

二、使用注意

代码分析:

1
2
Dog *d=[[Animal  alloc] init];   //动物是一条狗?语义正确吗?
NSString *str=[Dog  new];     //狗是一个字符串?正确吗?

OC语言是一门弱语法的语言,编译的时候并不会报错,所以这就要求我们在实际的开发过程中一定要按照既定的规范来写代码,不要出现狗是一个字符串这样的问题。

多态的好处:需要一个新的函数专门用来喂狗

1
2
3
4
void feed(Dog *d)
{
    [d  eat];
}

如果这个时候也需要喂猫,那就应该重写新一个新的函数

1
2
3
4
void feed(Cat *c)
{
    [c  eat];
}

而狗和猫实际上都继承自动物这个类,在这里就可以使用多态来简化代码了。

这里只需要把函数的参数写成是Animal *类型的,那么Dog和Cat类型的对象就都可以传入进来。

调用的时候直接改变参数就可以了。

多态的局限性:父类类型的指针变量不能直接调用子类特有的方法。

不建议的做法:

1
2
Animal *a=[[Dog alloc] init];
[a run];//在Animal类中没有run方法,这里调用了狗对象的方法。

解决方法:可以将a强制转换为Dog*类型的变量,如下:

1
Dog *d=(Dog *)a;//使用强制转换,这里a和d指向的是同一个狗对象

三、多态使用总结

  1. 没有继承就没有多态
  2. 代码的体现:父类类型的指针指向子类对象
  3. 好处:如果函数方法参数中使用的是父类类型,则可以传入父类和子类对象,而不用再去定义多个函数来和相应的类进行匹配了。
  4. 局限性:父类类型的变量不能直接调用子类特有的方法,如果必须要调用,则必须强制转换为子类特有的方法。

四、字符串补充内容

@“234”字符串也是一个对象,属于NSString这个类。下面是对字符串对象的一些代码说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 最简单的创建字符串的方式
NSString *str = @"xiaoming";
// 使用C字符串的方式创建字符串
char *name = "mingxiao";

// 打印字符串
NSLog(@"%s", name);
NSLog(@"%@在敲代码练习呢!", str);

int a = 5;
int b = 10;
// 创建字符串的另外一种方法
NSString *str1 = [NSString stringWithFormat:@"我已经敲了%d个小时,准备学够%d个小时", a, b];
NSLog(@"%@", str1);

// 打印结果
2016-07-12 20:08:00.171 test[70395:12064646] mingxiao
2016-07-12 20:08:00.171 test[70395:12064646] xiaoming在敲代码练习呢
2016-07-12 20:08:00.171 test[70395:12064646] 我已经敲了5个小时,准备学够10个小时

字符串对象的length方法:计算的是字符串的字数,而不是像strlen函数那样,计算的是字符数。如“哈ha123” length得出的结果是6,返回unsigned long类型,而strlen函数得出的结果是8,因为一个汉字占3个字节。

提示:字数也包括空格。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
NSString *str = @"xiaoming love read";
NSString *str1 = @"哈哈123";

// 请注意方法的返回值类型,这里使用 %d 打印
// legth 方法, 获取当前字符串的字数
NSLog(@"字数为%ld", [str length]);
NSLog(@"字数为%ld", [str1 length]);

// 打印结果
2016-07-12 20:10:41.136 test[70446:12072597] 字数为18
2016-07-12 20:10:41.137 test[70446:12072597] 字数为5