说明+示例+解释(您可以跳到问题部分)
我想创建一个对象实例,可以通过不同的实现来实现,具体取决于条件(互联网状态)。
简单声明
@interface LoginController : NSObject
/** The currently logged-in User. Nil if not logged-in yet. */
@property (strong, nonatomic) User *currentUser;
// Singleton object
+ (instancetype)shareInstance;
/** Abstract methods, will do nothing if call directly. Use inheritance implements (Online/Offline) instead. */
- (User *)loginByEmail:(NSString *)email password:(NSString *)pwd;
@end
@interface LoginControllerOnline : LoginController
// Login will call request to server.
@end
@interface LoginControllerOffline : LoginController
// Login will check data in coredata.
@end
LoginController的登录方法实际上什么都不做(return nil
)。相反,继承的类(在线/离线)用不同的实现覆盖父登录的方法(如在注释中)
然后,我有一个经理来定义应该使用哪个类:
@implement InternetManager
+ (LoginController *)loginController
{
return [self hasInternet] ? [LoginControllerOnline shareInstance] : [LoginControllerOffline shareInstance];
}
+ (BOOL)hasInternet
{
// Check with Reachability.
}
@end
这项工作。但这不是我想要实现的机制。
internetStatus
从offline
更改为online
时,我想重新登录(获取session / oauthToken ...)。但是,我必须做很多事情(复制用户,更改实例,检查保留...)才可以实际通过在线登录来打电话问题:
我有没有办法只创建一个LoginController
的实例,它拥有相同的属性(User
),但可以有不同的(动态)实现(在线/离线)?
更新问题:
引用Apple的Dynamic typing:
isa指针:
每个对象都有一个isa实例变量 标识对象的类。运行时使用此指针 在需要时确定对象的实际类。
那么,有没有办法让我更改对象实例的isa pointer
?
答案 0 :(得分:3)
听起来真正的问题是,你已经将这些东西直接归属于你实际上不希望他们拥有的国家的主要所有权 - 将其排除在外。没有复制,只需给每个在-init
编组状态的事件的实例,并允许他们与之交谈。
然后,当你想根据条件做一件事或另一件事时,做正常的编程事情:使用if
语句。
所以,我不认为使用动态运行时是合适的。然而,在学术上,假设有兴趣:
如果你真的必须这样做,请使用object_setClass
,这是“对象的类别”,回答你的实际问题。显然,您需要存储兼容,因此您的子类可能不应声明任何属性或实例变量。
此常规区域的常见替代方法是不更改现有实例的类,而是更改作为类成员的方法。所以你有两个-loginByEmail:password:
的替代实现,并设置哪个是实际响应该选择器的动态。但是,如果您可以访问源代码并且围绕其通常是间接的,不透明的性质,那么仅仅使用if
就没有优势了。整件事通常被称为混合。 class_replaceMethod
是关键组件,但只是搜索混合。