> On Aug 30, 2017, at 11:17 AM, Joanna Carter via swift-users
> <[email protected]> wrote:
>
> Hi Kenny
>
>> Just curious, and because I have a distinct lack of imagination: can you
>> share a concrete case of this pattern?
This is likely due to the runtime not handling cycles properly in type metadata
initialization—a subclass T needs its base class metadata for BaseObject<T>,
which in turn needs the metadata for T to instantiate the generic type. This is
something we plan to fix next year since it requires runtime ABI changes. For
the particular pattern you've described:
> class BaseObject<rootType>
> {
> private let properties: [PartialKeyPath<rootType> : AnyProperty]
>
> init(properties: [PartialKeyPath<rootType> : AnyProperty])
> {
> self.properties = properties
> }
>
> func value<valueType>(for keyPath: KeyPath<rootType, valueType>) ->
> valueType?
> {
> guard let property = properties[keyPath] else
> {
> return nil
> }
>
> return property.getValue()
> }
>
> func set<valueType>(value: valueType?, for keyPath: KeyPath<rootType,
> valueType>)
> {
> guard let property = properties[keyPath] else
> {
> return
> }
>
> property.set(value: value)
> }
> }
>
> class Test : BaseObject<Test>
> {
> var name: String?
> {
> get
> {
> return value(for: \.name)!
> }
> set
> {
> set(value: newValue, for: \.name)
> }
> }
>
> var number: Int?
> {
> get
> {
> return value(for: \.number)!
> }
> set
> {
> set(value: newValue, for: \.number)
> }
> }
>
> init()
> {
> super.init(properties: [\Test.name : Property<String>(), \Test.number :
> Property<Int>()])
> }
> }
>
> Without the generic rootType parameter, all the getter and setter methods
> need an explicit mention of the derived class for the keypath :
>
> class Test : BaseObject
> {
> var name: String?
> {
> get
> {
> return value(for: \Test.name)!
> }
> set
> {
> set(value: newValue, for: \Test.name)
> }
> }
>
> …
> }
Would a protocol-based approach suffice? `Self` in a protocol extension would
give you access to the concrete type in a similar way:
protocol Base: AnyObject {
var properties: [PartialKeyPath<Self> : AnyProperty] { get }
}
extension Base {
func value<T>(for keyPath: KeyPath<Self, T>) -> T?
{
guard let property = properties[keyPath] else
{
return nil
}
return property.getValue()
}
/*etc.*/
}
class Test: Base {
let properties = [\Test.name: Property<String>()]
var name: String {
get { return value(for: \.name) }
set { set(value: newValue, for: \.name) }
}
}
-Joe
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users