Rlyr Rlyr - 6 months ago 25
Swift Question

swift reflections: how to construct a new struct instance based on reflections?

My example consists of:


  • protocol with read-only properties

  • struct implementing that protocol

  • "+" operator function



I'd like the "+" operator to be able to work for all implementations of the protocol by creating a new instance of the specific type that implements that protocol.

As you can see in the source code below, the operator accepts parameters of type "Aable" (the protocol). Using the generic placeholder T to construct a new instance fails with the error "'Aable' cannot be constructed because it has no accessible initializers".

Is that even possible?

Could it be achieved using reflections or some sort of introspection?

protocol Aable {
var name: String { get }
}

func +(left: Aable, right: Aable) -> Aable {
let leftType = left.dynamicType
//error: 'Aable' cannot be constructed because
// it has no accessible initializers
return leftType(name: left.name + right.name)
}

struct A: Aable {
let name: String
}

let a1 = A(name: "A #1")
let a2 = A(name: "A #2")

a1 + a2

Answer

You don't need reflection and AableError.

First of all lets add an init to your protocol

protocol Aable {
    var name: String { get }
    init(name:String)
}

Now you want + operator where:

  • both params are of type Aable
  • the params have the same type
  • the return type is the same of the params

You can define this constraints with generics

func +<T:Aable>(left: T, right: T) -> T {
    return T(name:left.name + right.name)
}

Now the check is performed at compile time so there's no need of the throws.

Test #1

struct Box:Aable {
    let name:String
}
let amazon = Box(name: "Amazon")
let apple = Box(name: "Apple")
let res = amazon + apple
res.name // "AmazonApple"

Test #2

struct Box:Aable {
    let name:String
}

struct Box:Aable {
    let name:String
}

struct Bottle:Aable {
    let name:String
}

let box = Box(name: "Amazon")
let bottle = Bottle(name: "Water")
box + bottle
//  ^ compile error
Comments