简体   繁体   中英

Why can't I use a Metatype as a property on a struct in swift?

So I was wondering my playground crashes when I try to instantiate a struct with a Metatype as a property type but not when I do the same with a class.

Struct Version:

struct Dog {
    static func saySomething() {
        print("Woof")
    }
}

I created a struct PetOwner with a Metatype-bound property and it compiled.

struct PetOwner {
    let name: String
    let pet: Dog.Type
}

When I try to use it, the playground crashes.

// Crashes
let dogOwner = PetOwner(
    name: "Joe",
    pet: Dog.self
)

However, when I make PetOwner a class:

class PetOwner {
    let name: String
    let pet: Speaking.Type

    init(name: String, pet: Dog.Type) {
        self.name = name
        self.pet = pet
    }
}

Then I can instantiate that class and call the static method:

let dogOwner = PetOwner(
    name: "Joe",
    pet: Dog.self
)

dogOwner.pet.saySomething() // Woof

Why is this happening? The error message for trying to instantiate the struct version is pretty inscrutable:

error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.

The really weird part though is that if I make the Metatype protocol bound, then it works again with structs:

protocol Speaking {
    static func saySomething()
}

struct Dog: Speaking {
    static func saySomething() {
        print("Woof")
    }
}

struct PetOwner {
    let name: String
    let pet: Speaking.Type
}

// Works!
let dogOwner = PetOwner(
    name: "Joe",
    pet: Dog.self
)
dogOwner.pet.saySomething() // Woof

What am I missing here?

Is this what you are looking for?

//: Playground - noun: a place where people can play

import UIKit

struct Dog {
    static func saySomething() {
        print("Woof")
    }
}

struct PetOwner {
    let name: String
    let pet: Dog
}

let dog = Dog()

// Won't crash
let dogOwner = PetOwner(
    name: "Joe",
    pet: dog
)

dogOwner.pet

It looks like you are trying to access Dog.Type (you were calling Dog.self, where Dog was actually Dog.type... so you were doing Dog.type.self... I think?). Notice that in the struct must create a dog object, in the class, you do not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM