目标C-根据类型从基类创建具体的类实例 [英] Objective C - creating concrete class instances from base class depending upon type

查看:95
本文介绍了目标C-根据类型从基类创建具体的类实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仅举一个现实的例子,假设基本类是Vehicle,而具体类是TwoWheeler和FourWheeler.现在,车辆类型-TwoWheeler或FourWheeler由基类Vehicle决定.当我使用alloc-init方法创建TwoWheeler/FourWheeler的实例时,它调用如下所示的super实现来设置Vehicle类中定义的公共属性的值,其中一个是类型,它实际上决定了该类型是TwoWheeler或FourWheeler.

Just to give a real world example, say the base class is Vehicle and concrete classes are TwoWheeler and FourWheeler. Now the type of the vehicle - TwoWheeler or FourWheeler, is decided by the base class Vehicle. When I create an instance of TwoWheeler/FourWheeler using alloc-init method, it calls the super implementation like below to set the value of common properties defined in the Vehicle class and out of these properties one of them is type that actually decides if the type is TwoWheeler or FourWheeler.

   if (self = [super initWithDictionary:dict]){
     [self setOtherAttributes:dict]; 
      return self; 
    }

现在,当我得到一批车辆时,其中一些可能是TwoWheeler,而其他一些可能是FourWheeler.因此,我不能像这样直接创建TwoWheeler或FourWheeler的实例

Now when I get a collection of vehicles some of them could be TwoWheeler and others will be FourWheeler. Hence I cannot directly create an instance of TwoWheeler or FourWheeler like this

Vehicle *v = [[TwoWheeler alloc] initWithDictionary:dict];

有什么方法可以创建基类的实例,一旦知道类型,就可以根据类型创建子类的实例并返回它.对于当前的实现,这将导致无限循环,因为我从具体的类中调用了超级实现.

Is there any way I can create an instance of base class and once I know the type, create an instance of child class depending upon type and return it. With the current implementation, it would result in infinite loop because I call super implementation from concrete class.

当我不知道应该事先实例化哪个具体类时,什么样的完美设计才能处理这种情况?

What would be the perfect design to handle this scenario when I don't know which concrete class should be instantiated beforehand?

推荐答案

通常,这是通过 Factory .

如果您希望工厂成为基类的一部分,那很好,但是将来可能会引起问题.在目标C中,类方法可以构成良好的工厂.

If you want the factory to be part of the base class, that's fine but it may cause issues in the future. In Objective C, class methods make good factories.

+ (Vehicle *)vehicleWithDictionary:(NSDictionary *)dict
{
    if ([[dict objectForKey:kVehicleType] isEqualToString:@"TwoWheeler"]) {
        return [[[TwoWheeler alloc] initWithDictionary:dict] autorelease];
    } else if ([[dict objectForKey:kVehicleType] isEqualToString @"FourWheeler"]) {
        return [[[FourWheeler alloc] initWithDictionary:dict] autorelease];
    } else {
        return [[[Vehicle alloc] initWithDictionary:dict] autorelease];
    }
}

工厂可以是Vehicle类的一部分,并且照常使用.

The factory can be part of the Vehicle class and used as so.

// Instead of [[Vehicle alloc] initWithDictionary:dict]
Vehicle *vehicle = [Vehicle vehicleWithDictionary:dict];


更新

我想出了一种方法来完成要求的工作.让它作为一个闪亮的例子说明为什么这是一个坏主意,以及为什么您永远不应该这样做.

I came up with a way to do what was asked. Let it serve as a shining example of why it's such a bad idea and why you should never do it.

- (id)initWithDictionary:(NSDictionary *)dict
{
    self = [super init];
    if (self) {
        // If override is in the dictionary, then it mustn't try to call the subclass.
        if (![dict objectForKey:kOverride]) {
            NSMutableDictionary *overrideDict = [NSMutableDictionary dictionaryWithDictionary:dict];
            [overrideDict setObject:@"override" forKey:kOverride];

            if ([[dict objectForKey:kVehicleType] isEqualToString:@"TwoWheeler"]) {
                [self release];
                return [[[TwoWheeler alloc] initWithDictionary:overrideDict] autorelease];
            } else if ([[dict objectForKey:kVehicleType] isEqualToString @"FourWheeler"]) {
                [self release];
                return [[[FourWheeler alloc] initWithDictionary:overrideDict] autorelease];
            }
        }

        // init as normal
    }

    return self;
}

这篇关于目标C-根据类型从基类创建具体的类实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆