Swift is operator with type stored in variable
It means that is operator cannot be used with variables on the right side?
Correct. The right side of is
must be hard-coded at compile-time.
If you don't need polymorphism and your types are class types, you can use ===
to compare the dynamicType
of an instance with a class type. That's the only way you're going to get a type-in-a-variable on the right side of something in pure Swift.
Casting to a type held in a variable
Swift (currently) requires the Type assignment at compile time. You can do some things like this, but you will need to write a converter for each type combination you want to use, e.g:
func convertType(from item: Int) -> Float {
return Float(item)
}
var item: Float = convertType(from: 1)
I would caution going down this road and try and get used to Swift's way of doing things. If you absolutely need it you should be able to use some generic functions with a protocol like FloatConvertable
to handle this more simply.
Swift Is Type Check Operator
The type of the reference dog is Animal. Thus you can hand it to api that uses Animals. But the actual type behind the dog reference will be Dog. thus you can test for the actual type using is
and you can (down)cast to the actual type using as
Assigning operator function in variable
You cannot do this:
var operation = *
But, you CAN do this:
var operation:(Int, Int) -> Int = (*)
operation(4,2) // -> 8
Because *
has many overloaded types:
func *(lhs: UInt32, rhs: UInt32) -> UInt32
func *(lhs: Int32, rhs: Int32) -> Int32
func *(lhs: UInt64, rhs: UInt64) -> UInt64
func *(lhs: Int64, rhs: Int64) -> Int64
func *(lhs: UInt, rhs: UInt) -> UInt
func *(lhs: Int, rhs: Int) -> Int
func *(lhs: Float, rhs: Float) -> Float
func *(lhs: Double, rhs: Double) -> Double
func *(lhs: Float80, rhs: Float80) -> Float80
we have to explicitly specify which one.
Type casting with type in variable
No. The type cast is a compile time thing. It lets the compiler know what methods are available and how to do the linking.
You can use Mirror
to gather information about your object at runtime, but it looks like invoking methods dynamically can still only be done on classes derived from NSObject
.
Can I use a function stored in a variable as operator in Swift?
The best I can come up with is something like:
infix operator <-> {} // define the operator <->
func <-> (lhs:Int, rhs:Int) -> Int {
return arrowFunction(lhs, rhs)
}
let arrowFunction : (Int, Int) -> Int = (+)
println("\(2 <-> 7)")
Can I make a Swift data type infix operator?
You could do this with generics:
struct MyStruct<T>
{
var someNum: T
}
You can then explicitly state the dataType you wish to use by specifying the type on creation: let a = MyStruct<Int>(someNum: 4)
.
One thing Swift does that makes this all absolutely beautiful is derive the data type from the constructor, so you can also just do this:
let intStruct = MyStruct(someNum: 4)
let floatStruct = MyStruct(someNum: 5.0)
Swift: send type as argument and compare a variable's type with it
As the other answers have eluded to, you cannot use meta-types with is
. However, a nicer solution would be to simply use generics. This will allow Swift to infer the type you pass into the function, allowing you to write it as:
protocol Base : class {
var value: Int { get set }
}
class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}
var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]
func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects.filter{ $0 is T }.forEach{ $0.value = value }
}
updateElements(ofType: ObjectTypeB.self, withValue: 10)
You'll also want to make your Base
protocol class bound (: class
) in order to allow Swift to treat Base
typed instances as reference types (allowing you to do $0.value = value
).
Your previous code of:
var object = $0
object.value = value
would have worked for reference types, but not for value types – as object
here is simply a copy of $0
, so any mutations won't be reflected in the array. Therefore you should annotate your protocol to make it clear that your protocol isn't designed to be used with value types.
If you do want to be able to handle value types, you may want to consider using map
instead:
func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects = objects.map {
var object = $0
if object is T {
object.value = value
}
return object
}
}
Why Int and Float literals are allowed to be added, but Int and Float variables are not allowed to do the same in Swift?
In case of var sum = 4 + 5.0
the compiler automatically converts 4 to a float as that is what is required to perform the operation.
Same happens if you write var x: Float = 4
. The 4 is automatically converted to a float.
In second case, since you have explicitly defined the type of the variable, the compiler does not have the freedom to change is as per the requirement.
For solution, look at @Fabio 's answer
Related Topics
iOS 13 Modals - Calling Swipe Dismissal Programmatically
Accessibility (Voice Over) with Sprite Kit
Memory Problems When Switching Between Scenes Spritekit
How to Replace Limited Number of Occurrences in String
Calling Nsexception.Raise() in Swift
Can You Evaluate a String in Swift
How to Override Private Method and Call Super in Swift
Apple Vision - Barcode Detection Doesn't Work for Barcodes with Different Colours
Creating a Type Bound to a Certain Range in Swift
Compiler Cannot Infer Return Type
Not Getting Expected Delegate Calls When Trying to Restore In-App Purchases with Storekit
Swift Get Nsdata of a Video from Photos Library
Swift String Permutations Allowing the Same Strings
Swfitui List Make Scrolling Disabled
Cannot Subscript a Value of Type '[String:String]' with an Index of Type 'String'