I am extending SCNVector3 from Apple SceneKit with arithmetic operations with a number. I use generic for the number's type, but I have found out that I have to write at least two versions of each function, as this does not work:
extension SCNVector3 {
static func *<T> (left: SCNVector3, right: T) -> SCNVector3 {
return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}
and gives error Cannot invoke initializer for Type 'Float' with an argument list of type '(T)'
Looking at definition of Float in Apple documentation, I see that the most generic I can get is init<Source: BinaryFloatingPoint>
or init<Source: BinaryInteger>
.
So I have to rewrite the extension as following, making two almost identical functions for each operation:
extension SCNVector3 {
static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}
I can place AND in where
clause — by having two conditions after where
separated by a comma.
But is there any way I can place OR there?
Generics allow you to declare a variable which, on execution, may be assigned to a set of types defined by us. In Swift, an array can hold data of any type. If we need an array of integers, strings, or floats, we can create one with the Swift standard library.
Swift Generic Function In Swift, we can create a function that can be used with any type of data. Such a function is known as a Generic Function. Here's how we can create a generic function in Swift: // create a generic function func displayData<T>(data: T){ ... }
Generic Methods A type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.
Generic Where Clauses Type constraints, as described in Type Constraints, enable you to define requirements on the type parameters associated with a generic function, subscript, or type. It can also be useful to define requirements for associated types. You do this by defining a generic where clause.
Your basic implementation should start by this:
extension SCNVector3 {
static func * (vector: SCNVector3, scale: Float) -> SCNVector3 {
return SCNVector3(vector.x * scale, vector.y * scale, vector.z * scale)
}
}
The vector has Float
components therefore you should always multiplicate only by a Float
. That's how all operators in Swift work. If you have a different type, cast it before multiplicating, not as a side-effect of multiplication.
If you really want to pass other types, then you can use method overloading:
extension SCNVector3 {
static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
return left * Float(right)
}
static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
return left * Float(right)
}
}
There is no way how to define or in types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With