> • You’re getting a compiler error because of the difference between the
> representation of metatypes (Foo.Type for some type Foo) of concrete types
> (e.g. String, Int), and protocols (e.g. DefaultValueProvider). Some of the
> compiler folks can correct my exact use of terminology here, but the essence
> is this: when you as?-cast a type to a concrete type (e.g. type as?
> String.self), you’ll get a concrete metatype which can be used dynamically as
> you would a concrete type elsewhere. When you as?-cast a type to a protocol
> type (type as? DefaultValueProvider), however, you get a protocol-constrained
> metatype which is not concrete and cannot be used dynamically as you would
> statically. You can call statically-known protocol methods on the metatype
> (e.g. (type as! DefaultValueProvider).init()), but the concrete type is not
Unfortunately, I am only too aware of this limitation 😌
Essentially, what I am trying to achieve is to extend the functionality of
"any" type by wrapping it in a generic type that contains the functionality.
I have a perfectly valid, and very useful, hierarchy that provides, not only
change observation but also validation of properties when an attempt is made to
change their value. It also provides for encapsulation of all the property
values in an object for storage or transmission.
The essentials are :
The BaseObject holds the PropertyBag and forwards all calls to property setters
to the PropertyBag, which contains a subscript, indexed on the property name
that accesses the relevant Property.
The Property contains metadata about e.g. : whether the property is readonly, a
validation hook and a means of observing the change if it is valid.
In C#, it was easy to access the metadata of a type instead of having to create
an instance of that type to get to it, as in Swift. Not having complete
reflection is definitely a gaping hole in Swift.
All I really wanted, in this instance, is to be able to bind a Property<T> to
the metatype of T, as in C#'s MakeGenericType([typeArgs]) method thus
let metatype = type(of: aType)
for propertyType in metatype.propertyTypes
let property = type(of: Property<>).makeGenericType([propertyType])
Once the generic properties are "in the bag", they are accessed and manipulated
using the Visitor design pattern, thus allowing a heterogeneous collection of
properties that are all treated correctly, according to their bound type.
In brief, I wanted a heterogeneous collection of generic types, all of which
implement a non-generic protocol ; something that is perfectly possible now.
However, the "automatic" creation of the generic types into the non-generic
protocol, based on the parameter type, seems to be unattainable ; unless I
create a protocol that contains a factory method but that has then to be
adopted by each individual type I wish to wrap in the generic type ; which is
swift-users mailing list