创建后更改实例化对象的子类

时间:2011-02-26 12:44:19

标签: objective-c cocoa

我正在创建一个Cocoa库,用于连接我公司制作的嵌入式设备。我有一个超类,我们称之为Device,还有一些不同设备模型的子类,我们称之为Device1Device2等。

我需要支持设备模型的自动检测,可以在连接并登录设备后确定。由于登录代码对所有设备都是通用的,因此可以在超类中处理。登录后,设备将需要由其模型的相应子类表示。

我设想实例化Device超类的对象,登录设备读取模型,然后用适当的子类的实例替换对象,比如说Device1。我知道可以在-init方法中返回一个不同的对象,但我的问题是设备的通信可能很长,所以应该用回调/委托来实现。

是否可以在-init方法之后更改实例化对象的子类?或者是否有更简单/更好的方法来实现我想要做的事情?

2 个答案:

答案 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