我有一个带有一些{get}和{get set}变量和扩展的协议,我设置了前一个,并在初始化类时 - 设置后者。我想把它们全部归还字典,即:
protocol SomeProtocol {
var id: Int { get }
var name: String { get set }
var isItTrue: Bool { get }
}
extension SomeProtocol where Self: SomeClass {
var id: Int { return 1 }
var isItTrue: Bool { return true }
func classProps() {
var dict = [String: AnyObject]()
let mirrorSelf = Mirror(reflecting: self)
for mirrorChild in mirrorSelf.children { print(mirrorChild.label) }
}
}
class SomeClass {
// just a class, nothing special
}
class MirrorMe: SomeClass, SomeProtocol {
var name: String = "Some name"
}
class MirrorMirrorOnTheWall {
func talkToTheMirror() {
let mirrorThis = MirrorMe()
mirrorThis.classProps() // returns only "name" property
}
}
正如我在评论中写的那样,classProps
只返回我在子类中设置的协议变量。如何在镜像的子项中同时包含 id 和 isItTrue ?
P.S。抱歉这个蹩脚的例子,这只是一个简单的例子:)
答案 0 :(得分:4)
Mirror
来自the Language Reference - Mirror struct(我强调)
子结构的表示和可选的“显示风格” 任意主题实例。
描述部分---例如存储属性,集合元素, 元组元素,或者组成一个的活动枚举情况--- 特定实例。也可能提供“显示风格”属性 建议如何渲染这个结构。
属性id
(int
)和isItTrue
(bool
)可用于MirrorMe
的实例,但仅作为计算属性< / em>,因为MirrorMe
没有将这些实现为存储属性,而是使用它们的默认实现作为extension SomeProtocol where Self: SomeClass { ... }
的计算属性。因此,id
的计算属性isItTrue
和MirrorMe
不包含在MirrorMe
实例的子结构表示中,正如使用Mirror
的运行时内省所提供的那样
我们可以在一个更简单的例子中清楚地验证这一点:
class Foo {
// a stored property
let representedInIntrospection = 0
// a computed property
var notRepresented: Int { return representedInIntrospection }
}
Mirror(reflecting: Foo())
.children
.forEach { print($0.label, $0.value) }
/* Optional("representedInIntrospection") 0 */
总结:协议中蓝色打印的属性(带或不带关联的默认实现)永远不能自己存储属性(blueprinted属性的默认实现自然只能包含计算属性)。这意味着在应用此类/结构的实例的运行时内省时,将显示符合您的协议的类/结构中显式声明为存储属性的唯一属性。
最后,你永远不会提到为什么你想要一个类实例的存储属性的字典的原因,但是如果将这个用作生产目的则要小心。通常,作为Swift的类型安全语言的运行时内省应仅用于诊断和调试,即使它允许在运行时黑客中使用(例如,对于继承自NSObject
的类,使用KVO)。