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:
- Your IF will crash because your array allValues contains 0
elements and you are accessing the first one (that does not exist). 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
Add New Card Is Not Being Called in Stripe Paymentoptionviewcontroller
Generic Function with Binary Operations
Why Does Core Data Context Object Have to Be Passed via Environment Variable
Calculate Range of String from Word to End of String in Swift
Swiftui JSON Won't Print Title in Scrollview Hstack (But Will in List)
Popping Noise Between Audioqueuebuffers
What's The Correct Number Type for Financial Variables in Swift
How to Save Re-Ordered Tableview Cells to Core Data
How to Send Multiple Buttons in Button.Addtarget Action? Swift3
Swiftui Textfield Resets Value and Ignores Binding
Literal Numbers in Floatingpoint Protocol
How to Exit a Function Scope from Inner Function Using Swift
How to List All Available Patterns in a Scdynamicstorage
Cannot Convert Value of Type 'Foo!' to Expected Argument Type 'Foo!'
How to Cache Cells and Also Reuse Cells in a Collectionview That Has Avplayers Embedded in Each Cell