传递类类型以在方法

时间:2018-04-18 16:37:55

标签: swift4 swift4.1

为了减少这个应用程序中的剪切和粘贴代码,我试图传递类名,以便告诉方法应该以哪种方式处理某些数据。我有以下内容:

class MyClass : NSObject {
    var name : String = ""
}

class OneClass : MyClass {
    override init() {
        super.init()
        self.name = "One"
    }
}

class TwoClass : MyClass {
    override init() {
        super.init()
        self.name = "Two"
    }
}


class Thing : NSObject {
    func doStuff(withClass cls: AnyClass) -> String {
        let x = cls.init()
        return x.name
    }
}

let z = Thing()
print(z.doStuff(withClass: OneClass))
print(z.doStuff(withClass: TwoClass))

通过withClass cls: AnyClass解析器,我推动我将let x = cls()更改为let x = cls.init()。但是我最后两行有一个Expected member name or constructor call after type name错误。推荐的修复程序都会导致其他问题。

第一个建议是在类名后面添加()构造函数,会在这些行上引发新的错误:Cannot convert value of type 'OneClass' to expected argument type 'AnyClass' (aka 'AnyObject.Type')

采取第二个建议并将它们更改为OneClass.selfTwoClass.self可以消除解析器错误,但是当我执行代码时,它只会永远运行..永远不会出错,永远不会完成。< / p>

我在其他地方发现了一项建议,建议我应将Thing.doStuff()参数更改为MyClass而不是AnyClass,但这会导致另一组新问题。

首先,解析器开始抱怨cls.init()调用,并且它建议的一系列修复最终导致一些没有意义的事情:let x = cls.type(of:;; init)()。解析器最终在一个建议循环中,它在语句中间不断添加更多的分号。

其次,我回到最后两行调用doStuff()时输入的不匹配错误:Cannot convert value of type 'OneClass.Type' to expected argument type 'MyClass'

显然我没有把关于传递类型作为参数传到这里,但是我所做的谷歌搜索都没有让我找到解释我所看到的问题的东西。

2 个答案:

答案 0 :(得分:1)

通用的Swift方式怎么样。

代码将通用类型T约束为MyClass,因为它必须具有name属性。

class MyClass : NSObject {
    var name : String

    override required init() {
        self.name = ""
        super.init()
    }
}

class OneClass : MyClass {
    required init() {
        super.init()
        self.name = "One"
    }
}

class TwoClass : MyClass {
    required init() {
        super.init()
        self.name = "Two"
    }
}


class Thing : NSObject {
    func doStuff<T : MyClass>(withClass cls: T.Type) -> String {
        let x = cls.init()
        return x.name
    }
}

let z = Thing()
print(z.doStuff(withClass: OneClass.self))
print(z.doStuff(withClass: TwoClass.self))

或使用协议。

protocol Nameable {
    var name : String { get }
    init()
}

class MyClass : NSObject, Nameable { ...

...

class Thing : NSObject {
    func doStuff<T : Nameable>(withClass cls: T.Type) -> String {
        let x = cls.init()
        return x.name
    }
}

答案 1 :(得分:1)

要使其正常运行,您必须在init进行类型转换后在cls上致电NSObject.Type。此外,x.name仅在cls类类型包含该特定属性时才有效。这就是x被强制转换为MyClass的原因。

class Thing : NSObject
{
    func doStuff(withClass cls: AnyClass) -> String?
    {
        let x = (cls as? NSObject.Type)?.init()
        if let x = x as? MyClass
        {
            return x.name
        }
        return nil
    }
}

使用doStuff

致电ClassType.self
print(z.doStuff(withClass: OneClass.self))
print(z.doStuff(withClass: TwoClass.self))

如果您仍然遇到任何问题,请告诉我。