【问题标题】:How can I return instancetype in Swift [duplicate]如何在 Swift 中返回实例类型 [重复]
【发布时间】:2014-06-12 09:20:24
【问题描述】:

我想扩展一些类来返回运行时类型对象

例如,我创建类 A 的扩展

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

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

var b: B = B.niceObject()

谢谢

【问题讨论】:

标签: objective-c swift


【解决方案1】:

你可以做到。下面的操场代码。 niceObject() 必须返回的是 self()。此外,您必须在基类上有一个 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

【讨论】:

【解决方案2】:

有一个关键字 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()
     }
 }

【讨论】:

  • 我认为你提到的错误不是因为运行B.niceObject()。这是编译错误。似乎我们不能在扩展中使用 Self 除非我们可以返回对象类型 Self
  • @ZoonNooz 我试图解释为什么我们不能在 Swift 中返回 Self。虽然如果我们可以在该方法中将Self 作为类型访问会有所帮助。
  • 我现在明白你的意思了。顺便说一句,在我在 objc 中的情况下,我根据当前类型在 coredata 中查询 NSManagedObject。所以我可以将它作为 NSManagedObject 返回,当我调用函数时它将是子类类型。但不是很快。
【解决方案3】:

至少在协议中,你可以使用Self。这表示self 的实际类型。不过不确定是否有扩展...

比如看Equatable的定义:

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

【讨论】:

  • 请注意,例如,如果您对 Dictionary 执行 extension 并希望返回相同类型的 Dictionary,则必须执行 extension Dictionary { func changeSomeThing() -> Dictionary { return self } }
【解决方案4】:

当您使用来自 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多