在Objective -C中子类化单例类的正确方法是什么?

Rav*_*oni 14 singleton objective-c

我创建了一个单例类,我想创建一个类,它是这个单例类的子类,正确的方法是什么

Jon*_*eet 20

我不太了解Objective-C,但一般来说,单例类应该阻止子类化.如果你有一个基类的实例一个子类的实例,那么你实际上有两个对象你可以看作基本"单例"类的实例,不是吗?

一旦你有两个实例,它就不再是一个单独的了......而且这就抛开了存在多个子类的可能性,或者子类本身允许创建多个实例.

当然你可以改变你的基类,所以它只是有一种方法可以获得一个"默认"实例,但这与使它成为一个单例并不完全相同.

  • 它变成了`Doubleton`?哈哈 (18认同)

V1r*_*ru8 13

如果乔恩没有说服你不这样做,你应该这样做:

在你的超类中,使用[[[self class] alloc] init]so 初始化你的单例实例,然后你总是得到一个用于调用sharedInstance方法的类的实例.而且您不必覆盖子类中的sharedInstance方法.

 [SuperClass sharedInstance] //-> instance of SuperClass
 [SubClass sharedInstance] //-> instance of Class
Run Code Online (Sandbox Code Playgroud)

  • 只要静态变量在超类中,就只能实例化它的一个副本.好吧,如果你把它放在子类中(在这种情况下你也必须迁移sharedInstance方法),单独的概念不会被继承. (3认同)
  • 这是错误的.我尝试了[[[self class] alloc] init]和[[self alloc] init]并且他们都只返回了类型超类的单例 (2认同)

Dmi*_*try 8

我为单身人士做了一个"基类"的例子,你可以在这里查看:https://github.com/stel/DOSingleton


bde*_*ham 6

如果你允许实例化类和它的子类,Jon Skeet就是否真的有一个单例是一个很好的观点.把它放在一边,这是一个你可以使用的模式,所以你只需要在父类中定义一次共享实例的getter:

// this code goes in the implementation of the superclass

static Sprocket *defaultSprocket;

+ (instancetype) defaultSprocket
{
    if (defaultSprocket == nil)
        defaultSprocket = [[[self class] alloc] init];
    return defaultSprocket;
}
Run Code Online (Sandbox Code Playgroud)

这种方法具有以下优点:

  • 使用[self class]允许例如[SprocketSubclass defaultSprocket]返回SprocketSubclass而不是的实例Sprocket
  • 使用instancetype允许编译器对此方法的结果进行类型检查:它将Sprocket在您调用它时,+[Sprocket defaultSprocket]但是SprocketSubclass当您调用它时+[SprocketSubclass defaultSprocket].

值得注意的是,您可以在基类中定义此访问器方法,然后您不必在子类中执行任何操作!

(给NSHipster的帽子提示解释为什么instancetype这么酷,并且最近让我想起它.)

  • 这个解决方案有一个缺陷,如果你按顺序访问 [subclass defaultSprocket] 然后是 [class defaultSprocket],在后者上你会得到子类单例,而不是你想要的单例类。正确的解决方案是必须在两个类中都定义单例访问器,以便它们都有自己的静态变量保存每个实例。 (2认同)