如何在Swift中返回instancetype

时间:2014-06-12 09:20:25

标签: objective-c swift

我想对某个类进行扩展以返回运行时类型对象

例如,我创建了A类的扩展

extension A {
    class func niceObject() -> XXXXX { // in objective-c is instancetype
        return ....
    }
}

所以任何人都知道Swift中有instancetype关键字或者不替换xxxxx我可以在A的子类上调用此函数而无需手动转换

var b: B = B.niceObject()

由于

4 个答案:

答案 0 :(得分:42)

你可以做到。游乐场代码如下。它是self(),niceObject()必须返回。此外,您必须在基类上有一个required init。

class A {
    required init() {
    }

    func whatClassAmI() -> String {
        return "Class A"
    }
}

class B: A {
    required init() {
        super.init()
    } 
    override func whatClassAmI() -> String {
        return "Class B"
    }
}

let a = A()
let sa = a.whatClassAmI() // "Class A", of course

let b = B()
let sb = b.whatClassAmI() // "Class B", of course

extension A {
    class func niceObject() -> Self {
        return self.init()
    }
}

let aa = A.niceObject()
let saa = aa.whatClassAmI() // "Class A"

let bb = B.niceObject()
let sbb = bb.whatClassAmI() // "Class B", as required

答案 1 :(得分:19)

有两个地方允许使用关键字Self - 在协议中(参见Jean-Philippe Pellet的回答)和class方法的结果:

extension A {
    class func niceObject() -> Self? {
        return nil
    }
}

不幸的是,这对您没有帮助,因为以下内容无效

extension A {
     class func niceObject() -> Self? {
         //A can't be converted to Self
         return A()
     }
 }

错误是由于您从A

继承而导致的
class B : A {
}

然后

var b = B.niceObject()

实际上会返回一个A实例,该实例无法转换为SelfSelfB

@Grimxn找到了正确的解决方案(See his answer):

您必须向基类添加所需的初始值设定项,例如

class A {
   @required init() {
   } 
}

然后您可以使用self()

调用初始化程序
extension A {
     class func niceObject() -> Self {
         return self()
     }
 }

答案 2 :(得分:10)

至少在procotols中,您可以使用Self。这代表self的实际类型。不确定扩展,但是......

例如,请参阅Equatable

的定义
protocol Equatable {
    func ==(lhs: Self, rhs: Self) -> Bool
}

答案 3 :(得分:0)

当您使用Objective-C中的Swift API时,编译器通常会执行直接转换。例如,Swift API func playSong(name: String)在Objective-C中导入为- (void)playSong:(NSString *)name

但是,有一个例外:当你在Objective-C中使用Swift initializer时,编译器会将文本“initWith”添加到方法的开头,并正确地将第一个字符大写。原始初始化程序。

例如,此Swift初始值设定项init (songName: String, artist: String)在Objective-C中导入为- (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist