Swift: отражение переменных протокола
У меня есть протокол с некоторыми переменными { 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 в детей Mirror?
извините за дерьмовый пример, это всего лишь быстрый пример:)
1 ответ
Вычисленные свойства не представлены в самоанализе времени выполнения, предоставленном Mirror
Из справочника по языку - Зеркальная структура (выделено мной)
Представление подструктуры и необязательного "стиля отображения" любого произвольного субъектного экземпляра.
Описывает части - такие как хранимые свойства, элементы коллекции, элементы кортежа или регистр активного перечисления -которые составляют конкретный экземпляр. Может также предоставлять свойство "стиль отображения", которое предлагает, как эта структура может быть отображена.
Свойства id
(int
) а также isItTrue
(bool
) доступны для экземпляров MirrorMe
, но только как вычисленные свойства, как 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 */
Подводя итог: свойства, созданные в протоколе с соответствующей реализацией по умолчанию или без нее, никогда не могут быть сохранены сами по себе (реализации по умолчанию свойств с чертежами, естественно, могут содержать только вычисленные свойства). Это означает, что единственные свойства, которые явно объявлены как хранимые свойства в классе / структуре, которые соответствуют вашему протоколу, будут отображаться при применении интроспекции во время выполнения экземпляра такого класса / структуры.
Наконец, вы никогда не упоминаете причину, по которой вам нужен словарь хранимых свойств экземпляра класса, но позаботьтесь о том, чтобы использовать это в производственных целях. Как правило, интроспекция во время выполнения на безопасном языке типа, таком как Swift, должна использоваться только для диагностики и отладки, даже если она позволяет использовать ее во время хаков во время выполнения (например, с KVO для классов, унаследованных от NSObject
).