TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Help needed: Type annotations for generic types result in loss of generic flexibility

Forums > Swift

I’m having trouble using Swift generics for the first time; specifically in regard to writing type annotations for my generic types.

Essentially, I’m using a generic parent class for different materials in a game. My intent is to be able to use the parent class’ type annotation for function parameters and returns, but mentioning the parent class requires that I pass generic constraints that refer to one of the child types, which ultimately limits the usage of the generic to a single type. Here’s my example.

Note: I realize that I can use existential types in-place of generics, but I’m trying to allow Swift to use static dispatch, in the interest of performance.

Import Foundation

Class MaterialExample<T: MaterialSubtype> {
    let subtype: T

    init(subtype: T) {
self.subtype = subtype
    }//init

/*represents one of the child types, which will have it’s own nested type that conforms to MaterialSubtype*/
    enum PrimaryType: String, RawRepresentable {
        case metal
    }
}//MaterialExample

/* Each child type has its own implementation of 
Protocol MaterialSubtype that refers to its own uses. So, the child types pass their implementation of Subtype when their inheritance is declared.

Ultimately, I just use this protocol to enforce type safety in the hierarchy.*/
Protocol MaterialSubtype: RawRepresentable where RawValue: StringProtocol {}

Class Metal: MaterialExample<Subtype> {

    Enum Subtype: MaterialSubtype {
Case bar
    }//Subtype
}//Metal

Class Glass: Material<Subtype> {

    Enum Subtype: MaterialSubtype {
Case pane
    }//Subtype
}//Glass

Where I’m having issues is when trying to use the MaterialExample class is when I need to pass a MaterialExample object as a function parameter, or declare it as a return type for a function. When doing so, I’m required to reference its generic parameters, which ultimately eliminates its generic capabilities when used outside of itself:

These cause errors, but would retain MaterialExample’s generic flexibility:

Let genericMaterial: MaterialExample

Func someFunc(material: MaterialExample) {}

Func makeSomeMaterial() -> MaterialExample {
//some return statement 
}

Because of this, I’m required to write those same lines like this, limiting MaterialExample to one of its child classes:

Let genericMaterial: MaterialExample<Glass.Subtype>

Func someFunc(material: MaterialExample<Metal.Subtype>) {}

Func makeSomeMaterial() -> MaterialExample<Glass.Subtype> {
// some turn call
}

I want my type annotations for properties and methods to be as flexible as the MaterialExample class is intended to be, but the lack of ability to do so is making me feel like I’m missing something. Is there a way to accomplish my intent without using existential types?

3      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.