【问题标题】:Objective-C subclass and base class castingObjective-C 子类和基类转换
【发布时间】:2010-06-08 15:43:25
【问题描述】:

我将创建一个基类,它为所有子类实现非常相似的功能。这是在different question 中回答的。但我现在需要知道的是是否/如何转换各种函数(在基类中)以返回子类对象。这既适用于给定的函数,也适用于其中的函数调用。

(顺便说一下,我正在使用 CoreData)

作为基类中的一个函数(这是来自一个将成为我的子类的类)

+(Structure *)fetchStructureByID:(NSNumber *)structureID inContext:(NSManagedObjectContext *)managedObjectContext {...}  

并且作为给定函数内的函数调用:

Structure *newStructure = [Structure fetchStructureByID:[currentDictionary objectForKey:@"myId"]];
                                              inContext:managedObjectContext];

Structure 是我的子类之一,因此我需要重写这两个,以便它们是“通用的”并且可以应用于其他子类(无论是谁调用该函数)。

我该怎么做?

更新:我刚刚意识到在第二部分中实际上存在两个问题。您不能将 [Structure fetch...] 更改为 [self fetch...] 因为它是类方法,而不是实例方法。我该如何解决这个问题?

【问题讨论】:

  • 构造函数/初始化方法通常返回id,因为这个原因。

标签: objective-c subclass base


【解决方案1】:

如果我正确理解您的问题,我相信关键是 [self class] 习语。

就您的更新请求调用当前类的类方法而言,您可以使用[self class]。如:

Structure *newStructure = [[self class] fetchStructureByID:[currentDictionary 
                                              objectForKey:@"myId"]];
                                                 inContext:managedObjectContext];

编辑:我重做这个以根据@rpetrich 的评论返回id——只要你确定你正在调用-createConfiguredObject 的实例类型,就更干净,并且避免需要-isKindOfClass: .

至于第一部分,您可以只返回一个id(指向任何对象的指针)并记录它将返回一个与调用它的类相同的实例。然后在代码中,您需要在方法中实例化新对象的任何地方使用 [self class]。

例如如果你有一个-createConfiguredObject 方法,它返回调用它的同一类的一个实例,它的实现方式如下:

// Returns an instance of the same class as the instance it was called on.
// This is true even if the method was declared in a base class.
-(id) createConfiguredObject {
    Structure *newObject = [[[self class] alloc] init];
    // When this method is called on a subclass newObject is actually
    // an instance of that subclass
    // Configure newObject
    return newObject;
}

然后您可以在代码中使用它,如下所示:

StructureSubclass *subclass = [[[StructureSubclass alloc] init] autorelease];
subclass.name = @"subclass";

// No need to cast or use isKindOfClass: here because returned object is of type id
// and documented to return instance of the same type.
StructureSubclass *configuredSubclass = [[subclass createConfiguredObject] autorelease];
configuredSubclass.name = @"configuredSubclass";

作为参考,我所指的 -isKindOfClass: 并转换为正确的子类如下:

Structure *structure;
// Do stuff
// I believe structure is now pointing to an object of type StructureSubclass
// and I want to call a method only present on StructureSubclass.
if ([structure isKindOfClass:[StrucutreSubclass class]]) {
    // It is indeed of type StructureSubclass (or a subclass of same)
    // so cast the pointer to StructureSubclass *
    StructureSubclass *subclass = (StructureSubclass *)structure;
    // the name property is only available on StructureSubclass.
    subclass.name = @"myname";
} else {
    NSLog(@"structure was not an instance of StructureSubclass when it was expected it would be.");
    // Handle error
}

【讨论】:

  • “在转换为正确的子类之前”是什么意思?到目前为止,这对我帮助很大,还有一些方面我正在努力解决。特别是在尝试设置像 newObject.name = ... 这样的变量时,因为结构(在您的情况下是基类)没有名称,但子类有。在这种情况下,我是否只需要让 Structure 看起来也具有这些变量?
  • 抱歉回复晚了。我花了一段时间来实现它。这真的很有帮助,谢谢。
猜你喜欢
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
相关资源
最近更新 更多