在类型属性中键入信息

时间:2016-11-23 12:39:26

标签: swift

我正在尝试创建一个类型属性,其值取决于类名。我想写这样的东西,所以每种类型只计算一次属性:

<div class="content">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
</div>

但是这不起作用,因为// Doesn't work static var modifiedClassName: String = { let s = type(of: self) return String(describing: s).modified() }() 在闭包内不可用。我最接近的是

self

但是这个属性是在每次被调用时计算的,而不是我所追求的。

有没有办法在定义类型属性的闭包内访问类型信息?

4 个答案:

答案 0 :(得分:2)

您可以明确包含self的类型注释(在静态上下文中),例如

// dummy modified() method
extension String {
    func modified() -> String { return self }
}

class Foo {
    static let modifiedClassName: String = {
        let s = type(of: Foo.self)
        return String(describing: s).modified()
    }()
}

请注意,静态属性(默认情况下都是惰性的) do 允许延迟不可变属性,如上所述。除非你打算改变modifiedClassName属性的值(在一次性实例化之后,在第一次调用之后),你也可以让它成为不可变的。

在基类中使用它似乎很困难,因此self的使用会动态地解析为派生类的类型。我们可以简单地通过将它放在一个只调用一次的私有静态方法中来绕过示例中self的无效:在modifiedClassName实例化时:

extension String {
    func modified() -> String { return self }
}

class Foo {
    static let modifiedClassName: String = _getModifiedClassName()

    class func _getModifiedClassName() -> String {
        let s = type(of: self)
        return String(describing: s).modified()
    }
}

但是,即使从派生类调用,对静态属性modifiedClassName的调用也会解析为基类:

class Bar: Foo {}

print(Foo.modifiedClassName)       // Foo.Type
print(Bar.modifiedClassName)       // Foo.Type
print(Bar._getModifiedClassName()) // Foo.Type

所以从这个意义上讲,似乎self与上面Foo的实现中直接使用_modifiedClassName()没有什么不同。

可能使用Obj-C功能。

答案 1 :(得分:0)

您可以懒惰地声明您的变量。这意味着它只在您第一次调用它时才会被实例化,这允许您使用self而不具有计算属性。您的代码只需稍加调整即可。

lazy var modifiedClassName: String = {
    let s = type(of: self)
    return String(describing: s).modified()
}()

我在我的代码中使用它,并且从未见过实例化被多次调用。

希望这有帮助。

答案 2 :(得分:0)

这是我的想法:

代码

import Foundation

class Property<T> {

    let modifiedClassName: String
    init () {
        modifiedClassName = String(describing: type(of: T.self)) + Property.modificator
    }
    class var modificator:String {
        return "Class"
    }
}

class Foo {
    static let property1 = Property<Foo>()
    let property2 = Property<Foo>()
}

print("Foo.static.property1 = \(Foo.property1.modifiedClassName)")
let obj = Foo()
print("Foo.property2 = \(obj.property2.modifiedClassName)")

结果

enter image description here

答案 3 :(得分:0)

如果你不介意有一个无用的财产浮动,这是有效的。

class Foo {
    static var _modifiedClassNameComputer: String {
        let s = type(of: self)
        return String(describing: s) // .modified()
    }

    static let modifiedClassName = _modifiedClassNameComputer
}

print("\(Foo.modifiedClassName)") // "Foo.Type"