【问题标题】:Instantiate subclass from mother class intelligently智能地从母类实例化子类
【发布时间】:2014-06-21 10:58:11
【问题描述】:

假设我有一个 motheclass(抽象与否)Item 和两个子类 ItemAItemB 都继承自 Item

所有实例都是通过下面的方法基于一个NSDictionary创建的

-(id)initWithJSON:(NSDictionary *)d{

//first instantiate common properties from the motherclass
    if ([super initWithJSON:d]){
        //Do specific stuff for the subclass
    }
    return self;
}

现在假设我从 web 服务中获取一个数组,该数组可以包含要创建的 ItemA 和 Item。

目前我所做的是使用 if/then 条件来确定我将根据字典内容实例化哪个子类,例如:

 [(NSArray*)data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

            if ([obj[@"kind"] isEqualToString:@"A"])
                [interactions addObject:[[ItemA alloc] initWithJSON:obj]];
            else if ([obj[@"kind"] isEqualToString:@"B"])
                [interactions addObject:[[ItemB alloc] initWithJSON:obj]];
            else
            [interactions addObject:[[Item alloc] initWithJSON:obj]];

        }];

现在我的观点如下:有没有一种方法只有一行代码会 - 默认情况下 - 实例化一个 Item 对象,并基于 ItemA 或 ItemB 换句话说,如果在解析的 NSDictionary 参数中满足某些条件,我可以在母类 Item 的 init 方法中编写一些代码来实例化子类吗?

谢谢

【问题讨论】:

  • A 和 B 始终是 Item,所以只需 caat 并忽略它们是 A 还是 B。
  • @MarcoAcierno 我不明白

标签: ios objective-c class inheritance initialization


【解决方案1】:

在你的母类中,添加一个这样的便捷方法:

 +(instancetype)itemWithJSON:(NSDictionary *)obj {
        id item; 

        if ([obj[@"kind"] isEqualToString:@"A"]) {
            item = [[ItemA alloc] initWithJSON:obj];
        } else if ([obj[@"kind"] isEqualToString:@"B"]) { 
            item = [[ItemB alloc] initWithJSON:obj];
        } else {
            item = [[Item alloc] initWithJSON:obj];
        }

        return item;
 }

然后像这样使用它:

 [(NSArray*)data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
     [interactions addObject:[Item itemWithJSON:obj]];
 }];

【讨论】:

  • 封装了逻辑什么项目类型来初始化/甚至如何初始化它,在那个便利函数里面!
  • 似乎是一种好的和正确的方法,谢谢。想了想,但主要是想看看有没有其他的最佳实践。非常感谢!
【解决方案2】:

看看NSClassFromString

示例伪代码:

NSString *className = [NSString stringWithFormat:@"Item%@", obj[@"kind]];
Class metaClass = NSClassFromString(className);

*instance = [[metaClass alloc] initWithJSON:obj];

然后您将此行为封装在一个静态class factory method 到您的母类中。有关详细信息,请参阅 Daij-Djan 的答案。

【讨论】:

  • 谢谢,我过去已经这样做了,这很有效,而且非常方便。这一次不同子类的命名约定不是那么接近母类,这意味着添加 if/then 逻辑。仍然感谢您的支持!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多