1、面向对象的三大特性
- 封装性
- 继承性
- 多态性
2、类方法和对象方法
- 类方法: 以+开头 调用类方法: [类名 类方法]
- 对象方法:以-开头 调用对象方法:[对象名 对象方法]
- 类方法和对象方法可以同名:
比如: - (void) test;
+(void)test;是正确的
3、关键字self
self其实是个指针,谁调用了方法,seLf就指向谁
例子:
背景:一个类中有一个成员变量:_age
- (void)test{
int _age = 20;
NSLog(@"%d",_age);
}
//若要指向成员变量 _age,用self->_age
4、继承
继承使用注意:
- 不允许子类和父类拥有相同名称的成员变量
- 父类必须什么在子类的前面
重写
- 子类重新实现父类中的某个方法,覆盖父类以前的做法
组合关系
当Score类中的属性:int _cScore ; int _ocScore;
和Student类中的属性:int _cScore ; int _ocScore
虽然有部分相同的成员变量,但是不采用继承,因为在现实生活中,学生类继承分数类,不符合逻辑关系
符合逻辑的继承举例:Student类继承Person类 @interface Student: Person
若不符合逻辑的继承应该考虑到组合关系:在Student类中:Score *_score;
5、Super的作用
- 直接调用父类中的某个方法
- super处在对象方法中,那么就会调用父类的对象方法,super处在类方法中,那么就会调用父类的类方法
6、super的使用场合
- 子类重写父类的方法时想保留父类的一些行为
[super eat]//调用父类中eat这个方法
7、多态
- 父类指针指向子类对象
背景:Animal类是Dog的父类
Animal *a = [Dog new];
用一段代码来体验多态的好处
Animal类:
@implementation Animal
- (void)eat{
NSLog(@"动物吃东西");
}
@end
Cat类:在.h文件中已经继承了Animal类
@implementation Cat
- (void)eat{
NSLog(@"猫吃东西");
}
@end
Dog类:在.h文件中已经继承类Animal类
@implementation Dog
- (void)eat{
NSLog(@"狗吃东西");
}
@end
main文件中:
#import "Animal.h"
#import "Dog.h"
#import "Cat.h"
#import <Foundation/Foundation.h>
//喂食的函数
void feed(Animal *a)
{
[a eat];
}
int main(int argc, const char * argv[]) {
Dog *dog = [[Dog alloc] init];
Cat *cat = [[Cat alloc] init];
Animal *animal = [[Animal alloc] init];
feed(dog);
feed(cat);
feed(animal);
NSLog(@"---------------");
Animal *dog2 = [Dog new];
Animal *cat2 = [Cat new];
Animal *animal2 = [Animal new];
[dog2 eat];
[cat2 eat];
[animal2 eat];
}
输出结果:
2015-03-16 20:11:49.436 objective-c知识点[3651:39141] 狗吃东西
2015-03-16 20:11:49.437 objective-c知识点[3651:39141] 猫吃东西
2015-03-16 20:11:49.437 objective-c知识点[3651:39141] 动物吃东西
2015-03-16 20:11:49.437 objective-c知识点[3651:39141] —————
2015-03-16 20:11:49.437 objective-c知识点[3651:39141] 狗吃东西
2015-03-16 20:11:49.437 objective-c知识点[3651:39141] 猫吃东西
2015-03-16 20:11:49.438 objective-c知识点[3651:39141] 动物吃东西
多态的局限性
- 父类类型的变量不能调用子类的方法
解决方法:强制转换类型
8、NSString
- objective-c 字符串 @”chenfanfang” 也是一个对象,是一个NSString对象
- objective-c 字符串的创建不像常规对象的创建方法
常规对象的创建方法:Person *p = [Person new];
字符串的创建:
方法1:NSString *str = @"itcast;"
方法2:NSString *str = [NSString stringWithFormat:@"my age is %d",23];
方法3:NSString *str = [NSString stringWithString:@"chenfanfang"];
获取字符串的长度
int length = [str length];
//对应的点语法为 str.length
int length1 = str.length;
9、pragma mark 用来标记,注释
//会生成分割线的注释
#pragma mark - 注释
//不声成分割线的注释
#pragma mark 注释
10、点语法
注意:
- 点语法不是直接访问成员变量,不像java,oc访问成员变量唯一方法: 对象名->成员变量
点语法的本质:
- 其实点语法的本质还是调用方法
- 当使用点语法时,编译器会自动展开成相应的方法。
例如:
stu.age = 10;//编译器会自动展开成如下的方法
[stu setAge:10];
int age = stu.age;//展开为
int age = [stu age];
点语法的死循环注意
在set方法和get方法别用点语法,否则会产生死循环。以下两个方法会产生死循环
- (void)setAge:(int)age{
self.age = age;
//展开成:[self setAge:age];
}
- (int)age{
return self.age;
//展开成:return [self age];
}
@class
@class的使用场景
对于循环依赖关系来说,比方,A类引用B类,同时B类引用A类
A类中
#import "B.h"
@interface A:NSObject
{
B *b;
}
@end
B类中
#import "A.h"
@interface B:NSObject
{
A *a;
}
@end
以上这种代码编译会报错,当使用@class在两个类相互申明,就不会出现编译错误
@class使用概括
使用@class 类名;就可以引用一个类,说明一下它是一个类
@class和#import的区别
- #import方式会包含被引用类的所有信息,包括被引用类的变量和方法。@class方式只是告诉编译器在A.h文件中 B *b 只是类的申明,具体类里有什么信息,这不需要知道,等实现文件中真正用到时,才会真正去查看B类中信息。
- 如果上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来讲,使用@class方式就不会出现这种问题了。
- 在.m实现文件中,若果需要引用到被引用类的实体变量或者方法时,还需要使用#import方法引入被引用类。