Objective c 重新定义父类声明为NS_不可用的初始化器

Objective c 重新定义父类声明为NS_不可用的初始化器,objective-c,initialization,Objective C,Initialization,我想重新定义一个初始化器,它以前被父类声明为NS\u UNAVAILABLE 例如: @interface Parent : NSObject // Unavailable - (instancetype)init NS_UNAVAILABLE; // Some other (appropriate) initialiser - (instancetype)initWithWhatever:(id)whatever NS_DESIGNATED_INITIALIZER; @end 对子初始

我想重新定义一个初始化器,它以前被父类声明为
NS\u UNAVAILABLE

例如:

@interface Parent : NSObject

// Unavailable
- (instancetype)init NS_UNAVAILABLE;

// Some other (appropriate) initialiser
- (instancetype)initWithWhatever:(id)whatever NS_DESIGNATED_INITIALIZER;

@end
对子初始化器的任何调用都需要传播到父级指定的初始化器,这是有意义的

假设默认参数在子类上有意义,因此:

@interface Child : Parent

// Propagates to initWithWhatever:
- (instancetype)init NS_DESIGNATED_INITIALIZER;

@end

尽管初始化器由子类Xcode重新声明,但似乎仍然认为它不可用。有办法解决这个问题吗?

看起来这种行为在Xcode 8中得到了修复(在8.1中进行了测试)

我还有一些注意事项:

  • 要使您的
    子项
    实现完全完成,您应使用任何覆盖
    init或使其不可用。因为
    Child
    当然会从
    Parent
    继承这个初始值设定项

  • 如果您使
    init
    不可用,那么也可以使
    new
    不可用


  • 所以。从现在起,我们可以借助
    NS\u指定的初始化器
    NS\u不可用
    组合,在Objective-C中完全控制我们的初始化器。与Swift相比,它需要更多的工作,但我认为这是值得的。特别是如果你想让你的类更好地与Swift兼容的话。

    要感谢那些家伙,他们认为现在的静态类型编程语言是个好主意,破坏了Objective-C。Objective-C既不需要这样的装饰,也不符合Objective-C的基本思想。但是,你需要一个解决方案。由于对象初始化没有什么特别之处,特别是初始化方法没有什么特别之处,只需更改方法的名称即可。这不是你的解决方案吗?在子类中再次使用方法会导致Liskov出现问题。我知道它不符合Objc的初始化器概念,但一些基类对某些初始化器不再有意义(即,没有默认值,但需要额外的参数)这一事实使我经常解决这些问题。Objective-c的设计师们弄错了,我想我可以用一个不同的名字,但是什么
    initWithNothing
    ?在几层继承之后,这将走向何方?我同意,Objective-C as
    NS\u UNAVAILABLE
    的最新变化指向了错误的方向,但至少它使声明在Liskov的意义上变得更好。然而,显然,
    -initWithDefaults
    将是一个合适的名称。由于不需要正式为您添加
    NS\u UNAVAILABLE
    ,因此您仍然使用
    -initWithDefaults
    ,直到您想使用
    NS\u UNAVAILABLE
    。你说的是一个容易解决的问题。(顺便说一句:在许多编程语言中,它类似于
    final
    。)这根本不是我的意思,而是构造函数继承的整个概念是错误的。不应该继承构造函数。这一事实并没有损害Leskov的替换原则,因为只有在构造对象之后才适用(也许使用反射实例化是另一个问题,但我认为也不应该使用反射)。我不明白,它与
    final
    有什么相似之处?这个概念并没有错,与堆栈分配语言相比,它工作得更好。它类似于
    final
    ,因为基类决策是继承的,没有机会在子类中更改它。