我正在创建一个Cocoa库,用于连接我公司制作的嵌入式设备。我有一个超类,我们称之为Device
,还有一些不同设备模型的子类,我们称之为Device1
,Device2
等。
我需要支持设备模型的自动检测,可以在连接并登录设备后确定。由于登录代码对所有设备都是通用的,因此可以在超类中处理。登录后,设备将需要由其模型的相应子类表示。
我设想实例化Device
超类的对象,登录设备读取模型,然后用适当的子类的实例替换对象,比如说Device1
。我知道可以在-init
方法中返回一个不同的对象,但我的问题是设备的通信可能很长,所以应该用回调/委托来实现。
是否可以在-init
方法之后更改实例化对象的子类?或者是否有更简单/更好的方法来实现我想要做的事情?
答案 0 :(得分:1)
一种方法是使用NSProxy
的自定义子类的实例而不是Device
超类来处理初始登录和设备检测。您可以将NSProxy
设计为在设备类型已知后将其自身转换为适当的Device
子类的实例。
NSProxy
利用了Objective-C运行时系统的一个功能,它允许其实例在收到针对真实目标实例的消息时注意到它们。然后,代理可以将消息转发到其目标,或者将其自身转换为目标类型的实例并将消息转发给自己。 (听起来很奇怪,我知道,但在实践中非常酷。)
这是类描述的第一段:
NSProxy是一个抽象的超类 为行为的对象定义API 作为其他物品的替身或者 尚不存在的对象。 通常,给代理的消息是 转发到真实对象或原因 加载代理(或转换自身 进入)真实的对象。的子类 NSProxy可用于实现 透明的分布式消息传递 例如,NSDistantObject)或懒惰 实例化对象 创造成本很高。
您的NSProxy
实现可能包括连接,登录等所需的方法,但不 Device
类层次结构实现的方法。代理实例可以在检测到设备类型时选择目标类。然后,只要您发送由Device
实现的消息,而不是代理,就会自动将其变为该类的实例。
答案 1 :(得分:0)
我建议你创建一个factory某种类型来实例化你的具体Device子类,这样就可以删除像更改对象类这样的肮脏技巧,这可能是一个更清晰的解决方案,这里有一个粗略的例子。看起来像是:
@implementation DeviceFactory
+ (Device *) detectAndMakeDevice
{
// Do your detection code here, this assumes that Device1 and Device2 are
// both subclasses of Device.
Device * dev;
if(deviceConnected == kDevice1)
dev = [[Device1 alloc] init];
else if(deviceConnected == kDevice2)
dev = [[Device2 alloc] init];
else
dev = nil;
return dev;
}
@end