目标C - 从基类取决于类型创建混凝土类实例(Objective C - creating con

2019-07-30 05:27发布

只是为了给一个现实世界的例子,说的基类是汽车类和具体类是TwoWheeler和FourWheeler。 现在车辆的类型 - TwoWheeler或FourWheeler,是由基类的车辆决定。 当我使用的alloc-init()方法创建TwoWheeler / FourWheeler的一个实例,它调用超级实现像下面以设置在汽车类和这些特性的定义共同属性的值其中之一是类型实际上决定,如果类型是TwoWheeler或FourWheeler。

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

现在,当我拿到车的集合,其中一些可能是TwoWheeler和其他人将FourWheeler。 因此,我不能直接创建TwoWheeler的实例或FourWheeler这样

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

有没有什么办法可以创建基类的一个实例,一旦我知道是什么类型,创建取决于类型的子类的实例,并返回它。 当前实现,这将导致无限循环,因为我把从具体类的超执行。

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

Answer 1:

一般来说,这是用做工厂 。

如果你想在工厂成为基础类的一部分,这很好,但它可能会导致在未来的问题。 在Objective C,类方法做好工厂。

+ (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];
    }
}

工厂可以是车辆类的一部分并用作如此。

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

更新

我想出了一个办法做了询问。 让它充当为什么这是一个坏主意一个光辉的榜样,为什么你永远不应该这样做。

- (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;
}


Answer 2:

你应该使用抽象工厂作为继,类车辆将呼吁的方法,createInstance建立,这种方法有一个参数,这将决定如何创建考虑的例子

+ (Vehicle*) createInstance:(int)numberOfWheels
{
    if(numberOfWheels == 2)
    {
        return [[TwoWheeler alloc] init];
    }
    else
    {
        return [[FourWheeler alloc] init];
    }

    return nil;
}

你会这样称呼它

Vehicle *v = [Vehicle createInstance:2];


文章来源: Objective C - creating concrete class instances from base class depending upon type