Swift Cast Generics Type

Swift generic type cast

I agree with Oliver Borchert and Airspeed Velocity: this kind of problem should be addressed using a protocol.

However you can perform the cast you asked about using this syntax:

let values = allValues as Any as [Person]

Now I see 2 problems:

  1. Your IF will crash because your array allValues contains 0
    elements and you are accessing the first one (that does not exist).
  2. allValues could have a Person at the first element and something
    else at the second position. This makes dangerous a cast after having evaluated only the first element.

    Example

    class LifeForm {}

    class Person : LifeForm {}

    With T equals to LifeForm.

I think the following version is safer because you are directly evaluating the type T.

class Things<T>{
func doSomething() {
let allValues = [T]()
// populate allValues....
if T.self is Person.Type {
println("List of Person")
let values = allValues as Any as [Person]
}
}
}

Important: I provided this code just to show the syntax. I don't like this abborach (again, a Protocol would be better) because the class Things contains logic specific to Person.
Ideally Things should know nothing about Person because Things is a generic class.

Swift cast generic without knowing the type

It's a little difficult to understand what you're really trying to do here (please tell me it's something other than JSON parsing; I'm so tired of JSON parsing and it's the only thing people ever ask about), but the short answer is almost certainly no. Some part of that is probably a misuse of types, and some part of that is a current limitation in Swift.

To focus on the limitation in Swift part, Swift lacks higher-kinded types. It is not possible to talk about Array. This is not a type in Swift. You can only work with Array<Int> or Array<String> or even Array<T>, but only in cases where T can be determined at compile time. There are several ways to work through this, but it really depends on what your underlying problem is.

To the misuse of types side, you generally should not have if x is ... in Swift. In the vast majority of cases this should be solved with a protocol. Whatever you were going to do in the if, make it part of the Parent protocol and give it a default empty implementation. Then override that implementation in Child. For example:

protocol Parent {
func doSpecialThing()
}

extension Parent {
func doSpecialThing() {} // nothing by default
}

class Child<LiterallyAnyValue, SameAsThePrevious>: Parent {}

extension Child {
func doSpecialThing() {
print(self)
}
}

func foobar(parent: Parent) {
parent.doSpecialThing()
}

Thanks for the clarification; Promise is a great thing to play with. Your mistake is here:

In my resolution process I have to check if the PromiseSubscriber is a (let's say) PromiseHandler and if it is then call the handler that returns something and then resolve the subscribed promise with that value.

Your resolution process should not need to know if it's a handler or a catcher. If it does, then your PromiseSubscriber protocol is incorrectly defined. The piece it sounds like you're missing is a Result. Most Promise types are built on top of Result, which is an enum bundling either success or failure. In your scheme, handlers would process successful Results and ignore failing results. Catchers would process failing results and ignore successful Results. The promise resolution shouldn't care, though. It should just send the Result to all subscribers and let them do what they do.

You can build this without a Result type by using a protocol as described above.

protocol PromiseSubscriber {
associatedType Wrapped // <=== It's possible you've also missed this piece
func handleSuccess(value: Wrapped)
func handleFailure(failure: Error)
}

extension PromiseSubscriber {
func handleSuccess(value: Wrapped) {} // By default do nothing
func handleFailure(failure: Error) {}
}

class PromiseHandler<Wrapped> {
func handleSuccess(value: Wrapped) { ... do your thing ... }
}

class PromiseCatcher {
func handleFailure(failure: Error) { ... do your thing ... }
}

I recommend studying PinkyPromise. It's a nice, simple Promise library (unlike PromiseKit which adds a lot of stuff that can make it harder to understand). I probably wouldn't use a protocol here; the associatedtype makes things a bit harder and I don't think you get much out of it. I'd use Result.

Swift Cast to Generic Type with Constraint

You wrote this function signature:

func jsonToObj<T:DomainResource>(jsonStr: String) -> [T:DomainResource]

This says that the jsonToObj(jsonStr:) method returns a dictionary whose keys are of type T and whose values are of type DomainResource. It looks like you just want to write this function signature:

func jsonToObj<T:DomainResource>(jsonStr: String) -> [T]

Swift: Cast generic type into same generic type but with a subclass of associated type

I am afraid this is not currently possible as of Swift 2.1. Only the following conversions are supported

  • Built in collections types are covariant on their element type.
  • Conversions between function types are supported, exhibiting covariance in function result types and contravariance in function parameter types. (Cf. Xcode 7.1 Release Notes)

As Objective-C's generics support type variance, and given the progress made on function type conversions in Swift 2.1, I believe there is reason to believe type variance support will be added to Swift in the future. In the mean time, remember to file a radar, like jlieske has.

In the mean time you will have to copy the collection or use one of the builtin collection types.

Update since Swift become open source:
I believe the Complete generics section of Swift 3.0 Dev Roadmap indicates type variance will be addressed in 3.0. While type variance is not specifically called out, special cased exceptions in the standard library (which includes type variance) are.



Related Topics



Leave a reply



Submit