#import <Foundation/Foundation.h>
typedef enum{
SexMal='m',SexFem='f'
} Sex;
@interface Score :NSObject
{
@public
double mathScore,engScore,cScore;
}
@end
@implementation Score
@end
@interface Person :NSObject
{
//成员变量非public,而是提供get set方法访问,体现封装特性
int _age;//命名规范,一般成员变量名以_开头
double _weight;
char* _name;
Sex _sex;
}
- (void)setAge:(int)age;//get set方法的规范写法
- (int)age;
- (void)setWeight:(double)weight;
- (double)weight;
- (void)setName:(char*)name;
- (char*)name;
- (void)setSex:(Sex)sex;
- (Sex)sex;
- (void)eat;
- (void)exercise;
+ (void) testSuper;
+ (void) testSuper2;
@end
@implementation Person
- (void)setAge:(int)age{_age=age;}
- (int)age{return _age;}
- (void)setWeight:(double)weight{_weight=weight;}
- (double)weight{return _weight;}
- (void)setName:(char*)name{_name=name;}
- (char*)name{return _name;}
- (void)setSex:(Sex)sex{_sex=sex;}
- (Sex)sex{return _sex;}
- (void)eat
{_weight++;}
- (void) exercise
{_weight--;}
+ (void) testSuper
{//%@为输出OC字符串对象
NSLog(@"Person super=%d,self=%d,super class=%@,self class=%@",super,self,[super class],[self class]);
[self testSuper2];
}
+ (void)testSuper2
{
NSLog(@"Person testSuper2");
}
@end
@interface Student :Person
{
@public
int _studentNo;
Score* _score;//利用组合来降低耦合性
}
@end;
@implementation Student
- (void)eat
{
[super eat];
NSLog(@"Student eat...weight=%.2f",[self weight]);
}
- (void)exercise
{
[super exercise];
NSLog(@"Student exercise...weight=%.2f",[self weight]);
}
+ (void) testSuper//方法重写(override)
{
NSLog(@"Student super=%d,self=%d,super class=%@,self class=%@",super,self,[super class],[self class]);
//利用super调用Person类中的方法与利用Person直接调用并非完全一样
//用Person调用后,Person中testSuper方法中self指向Person类对象
//而利用super调用后,Person中testSuper方法中self指向Student类对象
[super testSuper];
[Person testSuper];
}
+ (void)testSuper2
{
NSLog(@"Student testSuper2");
}
@end;
@interface PrimaryStudent:Student
@end
@implementation PrimaryStudent
+ (void)testSuper2
{
NSLog(@"PrimaryStudent testSuper2");
}
@end
@interface Staff:Person
{
@public
int _staffNo;
}
@end
@implementation Staff
- (void)eat
{
[super eat];
NSLog(@"Staff eat...weight=%.2f",[self weight]);
}
- (void)exercise
{
[super exercise];
NSLog(@"Staff exercise...weight=%.2f",[self weight]);
}
@end
//利用OC多态特性,Person*可接收任意其子类对象
void eatSomething(Person* p)
{
[p eat];
}
void doExercise(Person *p)
{
[p exercise];
}
int main(int argc, const char * argv[])
{
Student * p=[Student new];[p setWeight:50];
Person * p2=[[Staff alloc] init];[p2 setWeight:60];
eatSomething(p);
doExercise(p2);
//测试super
[Person testSuper];
[Student testSuper];
[PrimaryStudent testSuper];
return 0;
}
/*
OC面向对象语法:
1>封装:
成员变量命名以_开始,非public,提供get set方法,
例 {int _age;} -setAge:(int)age; -(int)age;
2>继承:
NSObject与NSProxy为OC中两大root class,大部分类都继承NSObject,
NSObject类中声明了一个Class类型的指针变量isa,该指针指向该对象对应的类对象;
每个类对象中都有一个superClass指针变量,指向其父类的类对象,
该指针变量声明在Class类中,所有类加载进内存后都是一个类对象,类对象是Class类的实例;
子类继承父类,则拥有父类所有成员变量及方法,包括类方法与对象方法;
子类成员变量名不允许与父类重名(java成员变量可重名),但是方法名可以重复(重写);
OC调用方法时,会从子类到父类的层级顺序查找(通过类对象中的superClass指针变量查找父类方法);
父类声明的方法可以子类中实现;
继承缺点:
类与类之间关系太紧密导致代码耦合性太强;
有些场合可利用组合降低耦合性
*继承表示子类是父类
*组合表示A类拥有B类
super关键字:
(super本质上与 self不同,self是类的隐藏的参数变量,指向当前调用方法的对象(类也是对象,类对象),
另一个隐藏参数是_cmd,代表当前类方法的selector,
而super并不是隐藏的参数,它只是一个"编译器指示符")
调用方法时,使用[super methodName]可以调用父类的方法,对象方法则调用父类
对象方法,类方法中则调用父类的类方法,无法调用成员变量(java中super可以调用父类成员变量)
OC普通方法调用通过消息机制发送,调用
id objc_msgSend(id theReceiver, SEL theSelector, ...)方法,
receiver为调用该方法的对象或类对象指针,与self一样,SEL为方法选择器,...为动态方法参数,
该方法实现伪代码大致为
id objc_msgSend(id theReceiver, SEL theSelector, ...)
{
if theReceiver 是Class对象
{
根据theSelector在theReceiver中从当前类到父类顺序查找类方法;
}else if theReceiver是对象
{
根据theSelector在theReceiver->isa中从当前类到父类顺序查找对象方法;
}
找到后调用该方法,将theReceiver传给隐藏形参self
return theReceiver;
}
而当编译器遇到通过[super XXX]方式调用的方法则调用
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)方法,
super的结构为 struct objc_super {
id receiver;
Class superClass;
};
这里superClass即类对象中的superClass指针变量,
receiver为当前方法中的self ,类方法指向类对象,对象方法则指向对象;
该方法实现的伪代码大致是
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
{
通过SEL在super->superClass中查找到需要调用的方法的selector,
然后调用上面那个消息发送的方法
注:selector为方法的选择器,子类重写父类方法,他们的selector是不一样的;
return objc_msgSendSuper(super->receiver, selector, ...);
}
因此在每个有用到super的方法中,都会生成一个struct objc_super,
通过[super XXX]调用的方法中的self等于生成super的方法中的self;
多态:
父类指针可以接收任意子类对象实例
使用场景:函数参数设置为父类指针,可接收任意子类对象
*/
OC学习笔记02-OC中的面向对象语法表现 - 封装 继承与多态
最新推荐文章于 2023-06-27 19:50:37 发布