【问题标题】:Allocate or Initialize Subclass From Superclass从超类分配或初始化子类
【发布时间】:2011-04-23 15:27:54
【问题描述】:

我正在开发一个通用的 iOS 应用程序。在大多数情况下,我一直通过创建子类来处理设备差异,因此 RootViewController 是 RootViewController-iPad 和 RootViewController-iPhone 的子类。模式从 main.m 开始,我在其中进行设备检测,如下所示:

int retVal;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPad");
} else {
    retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPhone");
}

这种模式运行良好,并且最大限度地减少了代码重用。

在堆栈的更下方,我有一系列继承自通用超类 MasterDetailViewController 的视图控制器。这个超类需要一些特定于设备的代码,所以我正在考虑对其进行子类化,然后让超类自动分配或实例化最合适的设备特定子类。

在实现方面,如下所示:

+(id)allocWithZone:(NSZone *)zone {
    if ([[self class] isEqual:[MasterDetailViewController_iPad class]] || [[self class] isEqual:[MasterDetailViewController_iPhone class]]) {
        return [super allocWithZone:zone];
    } else {
        if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
            return [MasterDetailViewController_iPhone allocWithZone:zone];
        } else {
            return [MasterDetailViewController_iPad allocWithZone:zone];
        }
    }
}

此代码不起作用,是一种概念演示。有没有办法做我想做的事,还是我看错了?

编辑:为了清楚起见,超类和子类之间的数据是相同的。唯一的区别是几个方法实现。这个想法是子类化比设备特定的意大利面条代码更干净。

【问题讨论】:

    标签: objective-c inheritance


    【解决方案1】:

    您的代码可能不起作用,因为类方法中的self 是类对象,因此[self class] 的类。试试[self isEqual:[MasterDetailViewController_iPad class]]。你也可以反过来比较,像这样:

    + (id)allocWithZone:(NSZone *)zone {
        // Allocating a subclass, don't interfere
        if (![self isEqual:[MasterDetailViewController class]]) {
            return [super allocWithZone:zone];
        }
    
        // Select an appropriate subclass to create instead
        if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
            return [MasterDetailViewController_iPhone allocWithZone:zone];
        } else {
            return [MasterDetailViewController_iPad allocWithZone:zone];
        }
    }
    

    如果您有理由使用更多特定于设备的子类,这可能会更容易扩展。

    请注意,还有其他方法可以做到这一点。例如,代替特定于设备的子类,一个通用类可以分配和使用特定于设备的帮助器对象来处理需要不同的少数操作(有点像委托)。或者,您可以让基类的init 方法释放self,而不是覆盖allocWithZone:,而是分配并返回适当子类的新对象。或者您可以使用工厂方法来分配适当的设备特定子类。

    【讨论】:

    • 你在课堂问题上是对的,有点愚蠢的错误。我最终只是将子类化得更远。
    • 当试图解决在文档中发现的类似问题时,下一个建议:“不要覆盖 allocWithZone: 以包含任何初始化代码。取而代之的是特定于类的 init... 方法版本。” developer.apple.com/library/mac/documentation/Cocoa/Reference/…:
    猜你喜欢
    • 2016-06-13
    • 2020-02-05
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多