Swift中超类方法返回子类类型

10

我有这段代码:

class Dark: NSObject {
  class var className: String {
    return NSStringFromClass(self)!.componentsSeparatedByString(".").last!
  }

  var success = 0

  class func devour<T: Dark>(params: Int) -> T {
    var s = T()
    return assign(s, params: params)
  }

  class func assign<T: Dark>(item: T, params: Int) -> T{
    if item.dynamicType === self {
      item.success = params
    }
    return item
  }
}

class Black: Dark {
}

class Violet: Dark {
}

Black.className // returns "Black"
Violet.className // returns "Violet"

问题出现在我执行以下操作时:
var ret = Black.devour(5)
ret.success //returns 0 which I expect to be 5

ret.self // returns {Dark success 0} which I expect to be {Black success 0}

这里的问题在于,当子类使用继承的方法devour时,它返回一个类型为Dark的对象。我希望在调用devour时能够返回子类的类型而不是超类的类型。例如,当我执行以下操作时:

var ret = Black.devour(5)

ret的类应该是Black而不是Dark

我希望有人能帮助我解决这个问题。我已经没有什么好的主意了。谢谢! 我想避免链接,我认为这是最后的选择。


你的问题是什么?请提供错误日志。 - Robin Ellerkmann
请参见以下链接:https://dev59.com/9V8d5IYBdhLWcg3w6luM - qwerty_so
嗨@RobinEllerkmann:这里的问题是,当子类使用继承的方法devour时,它返回一个类型为Dark的对象。我希望在调用devour时能够返回子类类型而不是超类类型。 - oregon
1个回答

8
原来我能够做一个变通; 多亏了这个问题的答案:Cast to typeof(self)
我需要做的就是创建一个返回 Self 类型对象的方法。首先,我创建了一个类,它创建了一个基类的实例并将其作为 AnyObject 实例返回。
    class func createDark() -> AnyObject {
          var black = Black()
          return black
    }

当我返回一个 Black 实例时,它会自动将其转换为 AnyObject,因为它是方法指定的返回类型(老实说,我才刚刚明白这一点,这真帮了我一个大忙)。

然后我创建了一个辅助方法,调用 createDark() 并为实例分配属性/属性:

    class func prepare<T: Dark>(params: Int) -> T{
        var dark = createDark() as T
        dark.assign(params)
        return dark
    }

我使用了泛型类型,该类型是Dark类型或其子类作为返回类型。

然后我做了这个操作:

    class func devour(params: Int) -> Self {
        return prepare(params)
    }

通过指定Self作为返回类型,它会自动将其转换为与Dark类型或任何继承它的类相同的类型。
我的最终代码如下:
class Dark: NSObject {
    var success = 0

    func assign(params: Int) {
        if self.dynamicType === self { // I dont really have to do this anymore
            self.success = params
        }
    }

    class var className: String {
        return NSStringFromClass(self)!.componentsSeparatedByString(".").last!
    }

    class func createDark() -> AnyObject {
        var black = Black()
        return black
    }

    class func prepare<T: Dark>(params: Int) -> T {
        var dark = createDark() as T
        dark.assign(params)
        return dark
    }

    class func devour(params: Int) -> Self {
        return prepare(params)
    }


}

检查是否解决了问题:

var ret = Black.devour(5)
ret.success //now returns 5 as expected

ret.self // now returns {Black success 0} as expected

正如预期的那样工作!


6
如果您在超类中必须显式编写Black(),那还有什么意义呢?如果我想要对紫色(Violet)或一些尚未存在的子类执行相同操作呢? - Balazs Vadnai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接