Hi Itai

>       • 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 
> known.

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

// pseudocode
  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 
messy 😉


Joanna Carter
Carter Consulting

swift-users mailing list

Reply via email to