类间两种关系:继承、 组合

类间两种关系:继承、 组合。类间非继承关系,而调用了其它类的对象方法或访问了其它类的成员变量,那么他们间的关系统称组合关系。
广义上讲,组合也包含另两个特别的情况:单例访问、 通过根控制器或导航控制器找到对应页面控制器进行操作。
第一种关系:继承。
大家都知道通过父子类的继承关系,子类对象可以访问父类对象的公有成员变量和公有成员函数,这个就不多说了。
@interface SettingProfileHeadCell : SettingProfileCell
@property UIImageView *headImageView;
@property UILabel *describeLabel;
@end
第二种关系:普通组合关系。
类间的组合关系大家也经常用,一个类的成员对象是另一个类的对象。这个也不难了解。
它又包含两种情况:
1.生成的另一个类的对象是本类的一个成员对象。
2.生成的另一个类的对象是本类的成员函数的一个临时对象,随着本类的成员函数的调用结束,系统就销毁了该临时对象。
第一种情况:
生成的另一个类的对象是本类的一个成员对象的声明部分
@interface DrawMoneyViewController ()
{
}
@property CustomCommonNavigationBar *customCommonNavigationBar;
@end
@implementation DrawMoneyViewController
生成对象的部分:
- (void)setupSubViews {
self.view.backgroundColor = BACKGROUND_COLOR;
_customCommonNavigationBar = [[CustomCommonNavigationBar alloc] initWithLeftBtnImageName:@”NavBar_icon_Back_dark” LeftBtnShift:19 RightBtnTitle:@”” title:@”提现” titleIsBold:NO];
[self.view addSubview:_customCommonNavigationBar];
_customCommonNavigationBar.sd_layout
.leftSpaceToView(self.view, 0)
.rightSpaceToView(self.view, 0)
.topSpaceToView(self.view, 0)
.heightIs(64 + LINE_THICK); // 设置高度约束
[self loadButtonAction];
}
使用页面控制器包含的控件block:
-(void)loadButtonAction
{
[_customCommonNavigationBar backResult:^(BOOL iSuccess) {
[self.navigationController popViewControllerAnimated:YES];
}];
}

第二种情况:成员函数临时变量的数据序列化例子:
- (void)storageDataModelWithFileName:(NSString *)fileName
dataArr:(NSMutableArray *)dataArr;
{
if(![fileName isKindOfClass:[NSString class]] || ![dataArr isKindOfClass:[NSMutableArray class]] || (dataArr.count == 0))
{
return;
}
NSString *plistFileName = [fileName stringByReplacingOccurrencesOfString:@” ” withString:@”“];
if(plistFileName.length == 0)
{
return;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSFileManager* fm = [NSFileManager defaultManager];
NSString *path=[paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:LOCATION_DATA];
if (![fm fileExistsAtPath:path])
{
[fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *filePath = [path stringByAppendingPathComponent:plistFileName]; //获取路径
if([plistFileName isEqualToString:ORDER_CENTER_PLIST_FILE_NAME])
{
OrderOperateModel *orderOperateModel = nil;
NSMutableArray *arr = [NSMutableArray array];
for(NSUInteger i = 0; i < dataArr.count; i++)
{
OrderCellModel *model = dataArr[i];
if(![model isKindOfClass:[OrderCellModel class]])
{
return;
}
orderOperateModel = [[OrderOperateModel alloc] initWithDictionary:model];
[arr addObject:orderOperateModel];
}
if(arr.count > 0)
{
NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:arr];
[tempArchive writeToFile:filePath atomically:YES];
}
}
}
第二种情况:成员函数临时变量的页面跳转例子:
-(void)openOnlineServiceViewController : (NSMutableDictionary *)orderInfo
{
OnlineServiceViewController *onlineServiceViewController = [OnlineServiceViewController new];
[onlineServiceViewController displayOrderInfo : orderInfo];
[self.navigationController pushViewController:onlineServiceViewController animated:YES];
}

特殊的组合关系:单例访问。
一个类的对象中的函数可以访问全局的单例。
使用系统的单例的block:
__weak typeof(self) weakSelf = self;
AppDelegate app = (AppDelegate )[UIApplication sharedApplication].delegate;
[app regisiterXYContinueListenOrderCallback:^{
[weakSelf continueListenOrder];
}];
使用单例的变量:
[SingleObject sharedInstance].keyboardWasShownFlag = NO;
使用单例的函数:

[[SingleObject sharedInstance] initData];
使用单例的block:

[[SocketManager shareInstance] regisiterOnlineServiceCallBackMessageCallBack:^(NSMutableDictionary *message) {
    [weakSelf handleMessageWithMessage:message];
}];

特殊的组合关系:通过根控制器或导航控制器找到对应页面控制器进行操作。
它和第二种关系的主要区别是它不是直接在本类生成该对象,而是找到已经存在的对象,并进行操作。
它和第三种关系的主要区别是它不是直接找到该对象,而是通过根控制器(也可能是导航控制器)找到,甚至根控制器(也可能是导航控制器)也是被间接找到的。
在一个页面控制器里可以通过导航控制器找到其它页面控制器,对它的公有成员数据进行赋值,也可以对它的公有函数进行调用,一般近接着就要跳到找到的这个页面控制器。
-(void)openOnlineServiceViewController : (NSMutableDictionary *)orderInfo
{
for (UIViewController *viewController in self.navigationController.viewControllers) {
if ([viewController isKindOfClass:[OnlineServiceViewController class]]) {
OnlineServiceViewController onlineServiceViewController = (OnlineServiceViewController )viewController;
[self.navigationController popToViewController:onlineServiceViewController animated:YES];
return;
}
}
OnlineServiceViewController *onlineServiceViewController = [OnlineServiceViewController new];
[onlineServiceViewController displayOrderInfo : orderInfo];
[self.navigationController pushViewController:onlineServiceViewController animated:YES];
}
在一个页面控制器里或非页面控制器里可以通过keyWindow找到rootViewController,然后通过它可以找到本导航控制器,然后通过本导航控制器找到指定的页面控制器,对它的公有成员数据进行赋值,也可以对它的公有函数进行调用,一般近接着就要跳到找到的这个页面控制器。
所以这种情况算着上一种情况的一种特殊情况。
使用这种方式找页面控制器时要注意一下三种情况:
1.当你在高德导航地图页面,你找到的就不是rootViewController了,是导航地图图层。
2.若你的页面出现了循环跳转,当使用该方法循环跳转了多次,你再用该种方法找页面可能出现异常情况(我的首页使用了两个子试图,一个做侧边栏,一个作普通的首页,在两个子试图间产生页面循环,使用该方法多次循环跳转后崩溃。估计普通的循环页面跳转使用该方法不会产生崩溃)。
3.当你的页面有多于一个导航控制器时(如:有侧边栏的应用),要注意导航控制器的层级。
-(void)goToLoginViewControlNotification
{
NSArray *cv = [[self getCurrentVC] childViewControllers];
NSLog(@”%@”,cv);
if(cv.count == 0)
{
return;
}
[[GlobalShare getGlobalShare] clearUserInfo];
UIViewController viewCtrl = (UIViewController )(cv[0]);

if([viewCtrl isKindOfClass:[LoginViewController class]])
{
    return;
}
for (UIViewController *viewController in self.navigationController.viewControllers) {
    if ([viewController isKindOfClass:[LoginViewController class]]) {
        [self.navigationController popToViewController:viewController animated:YES];
    }
}

}

  • (UIViewController *)getCurrentVC
    {
    UIViewController *result = nil;

    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    if (window.windowLevel != UIWindowLevelNormal)
    {
    NSArray *windows = [[UIApplication sharedApplication] windows];
    for(UIWindow * tmpWin in windows)
    {
    if (tmpWin.windowLevel == UIWindowLevelNormal)
    {
    window = tmpWin;
    break;
    }
    }
    }
    UIView *frontView = [[window subviews] objectAtIndex:0];
    id nextResponder = [frontView nextResponder];

    if ([nextResponder isKindOfClass:[UIViewController class]])
    result = nextResponder;
    else
    result = window.rootViewController;

    return result;
    }

(1)抽象:从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征,就叫作抽象。抽象是形成概念的必须手段。 抽象原则有两方面的意义:第一,尽管问题域中的事物是很复杂的,但是分析员并不需要了解和描述它们的一切,只需要分析研究其中与系统目标有关的事物及其本质性特征。第二,通过舍弃个体事物在细节上的差异,抽取其共同特征而得到一批事物的抽象概念。 抽象是面向对象方法中使用最为广泛的原则。抽象原则包括过程抽象和数据抽象两个方面。 过程抽象是指,任何一个完成确定功能的操作序列,其使用者都可以把它看作一个单一的实体,尽管实际上它可能是由一系列更低级的操作完成的。 数据抽象是根据施加于数据之上的操作来定义数据类型,并限定数据的值只能由这些操作来修改和观察。数据抽象是OOA的核心原则。它强调把数据(属性)和操作(服务)结合为一个不可分的系统单位(即对象),对象的外部只需要知道它做什么,而不必知道它如何做。 (2)封装就是把对象的属性和服务结合为一个不可分的系统单位,并尽可能隐蔽对象的内部细节。 (3)继承:特殊类的对象拥有的其一般类的全部属性与服务,称作特殊类对一般类的继承。 在OOA中运用继承原则,就是在每个由一般类和特殊类形成的一般-特殊结构中,把一般类的对象实例和所有特殊类的对象实例都共同具有的属性和服务, 一次性地在一般类中进行显式的定义。 在特殊类中不再重复地定义一般类中已定义的东西,但是在语义上,特殊类却自动地、隐含地拥有它的一般类 (以及所有更上层的一般类)中定义的全部属性和服务。继承原则的好处是:使系统模型比较简练也比较清晰。 (4)分类:就是把具有相同属性和服务的对象划分为一类,用类作为这些对象的抽象描述。分类原则实际上是抽象原则运用于对象描述时的一种表现形式。 (5)聚合:又称组装,其原则是:把一个复杂的事物看成若干比较简单的事物的组装体,从而简化对复杂事物的描述。 (6)关联:是人类思考问题时经常运用的思想方法:通过一个事物联想到另外的事物。能使人发生联想的原因是事物之间确实存在着某些联系。 (7)消息通信:这一原则要求对象之间只能通过消息进行通信,而不允许在对象之外直接地存取对象内部的属性。通过消息进行通信是由于封装原则而引起的。在OOA中要求用消息连接表示出对象之间的动态联系。 (8)粒度控制:一般来讲,人在面对一个复杂的问题域时,不可能在同一时刻既能纵观全局,又能洞察秋毫。因此需要控制自己的视野:考虑全局时,注意其大的组成部分,暂时不详察每一部分的具体的细节;考虑某部分的细节时则暂时撇开其余的部分。这就是粒度控制原则。 (9)行为分析:现实世界中事物的行为是复杂的。由大量的事物所构成的问题域中各种行为往往相互依赖、相互交织。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值