Home > database >  How to check if Data Type equals Generic Data Type and assign to Property if True?
How to check if Data Type equals Generic Data Type and assign to Property if True?

Time:08-28

Context

I have a Generic Swift Class containing a component Property of the Generic Type. A few other Variables with different Data Types are passed through the Initializer, however, all of them are conforming to the Generic Protocol.

However, I get the following Compiler Error in Line 11:

'ComponentA' is not convertible to 'C'


Code

protocol Component { ... }

struct ComponentA: Component { ... }
struct ComponentB: Component { ... }

class Main<C: Component> {
    var component: C

    init(componentA: ComponentA, componentB: ComponentB) {
        // I am trying to check, whether componentA equals the Generic Data Type and assign it to the component Property if true.
        if case let safeComponent = componentA as C {
            self.component = safeComponent
        }
    }
}

Question

How can I achieve my goal of checking whether a Data Type equals the Generic Data Type and assign it to the component Property if true?

CodePudding user response:

You need to Check for componentA compatibility with C. For example :

protocol Component {
    var name: String {get}
    
}

struct ComponentNil: Component {
    var name: String
}

struct ComponentA: Component {
    var name: String
    var a: Int
}
struct ComponentB: Component {
    var name: String
    var b: Int
}

class Main<C: Component> {
    var component: C
    
    init(componentA: ComponentA, componentB: ComponentB) {
        // Check that componentA is compatible with type C
        if let safeComponent = componentA as? C {
            self.component = safeComponent
        } else {
            // force componentB to be of type C
            self.component = componentB as! C
            // not that this may throw an error
        }
    }
}

CodePudding user response:

You have at least 3 possible approaches. All deal with the possibility that componentA can not be cast to C

protocol Component {  }

struct ComponentA: Component {  }
struct ComponentB: Component {  }

// optional `component`
class Main1<C: Component> {
    var component: C?

    init?(componentA: ComponentA, componentB: ComponentB) {
        if let safeComponent = componentA as? C {
            self.component = safeComponent
        }
    }
}

// init throws when precondtions not met
class Main2<C: Component> {

    enum Errors: Error {
        case preconditionsNotSatisfied
    }

    var component: C

    init(componentA: ComponentA, componentB: ComponentB) throws {
        if let safeComponent = componentA as? C {
            self.component = safeComponent
        } else {
            throw Errors.preconditionsNotSatisfied
        }
    }
}


// init can return nil
class Main3<C: Component> {
    var component: C

    init?(componentA: ComponentA, componentB: ComponentB) {
        if let safeComponent = componentA as? C {
            self.component = safeComponent
        } else {
            return nil
        }
    }
}
  • Related