Pixel
Pixel

Reputation: 171

Swift Custom Variable Type

For working with complex numbers, this is how I've been doing it:

import Foundation

class Complex {
    var real: Float
    var imaginary: Float
    init(re: Float, im: Float) {
        self.imaginary = im
        self.real = re
    }
    func abs() -> Float {
        return sqrtf(powf(self.real, 2) + powf(self.imaginary, 2))
    }

    func string() -> String {
        if (ceilf(self.real) == self.real) && (ceilf(self.imaginary) == self.imaginary){
            return "\(Int(self.real))+\(Int(self.imaginary))i"
        }
            return "\(self.real)+\(self.imaginary)i"
    }

    func arg() -> Float {
            return atan2f(self.imaginary, self.real)
    }
}

var someComplex = Complex(re: 2, im: 3)
var someComplexString = someComplex.string() //"2+3i"
var someComplexAbsolute = someComplex.abs() // 3.60...
var someComplexArgument = someComplex.arg() //0.98...

Now I was wondering, if there was any way to define a custom type of variable that would let me write it as someComplex: Complex = 3i for example. Is it possible to create a new type "from the ground up"?

Upvotes: 3

Views: 5956

Answers (1)

dfrib
dfrib

Reputation: 73186

I'm slightly uncertain if this is what you're looking for, but based on your comment to the other answer

"Thanks, but what I meant was something like a custom type that would accept all floats and i for example",

you could create a wrapper that holds a single generic value, where the generic type of this value is type constrained to some protocol, to which you in turn extend the types you wish to be wrappable but the type. E.g., below allowing types Int, Float and String to be wrapped by the wrapper

protocol MyGenericTypes { }

extension Int: MyGenericTypes { }
extension Float: MyGenericTypes { }
extension String: MyGenericTypes { }

struct SomeWrapper<T: MyGenericTypes> {
    var value: T
    init(_ value: T) {
        self.value = value
    }
}

let myInt = 42
let myFloat: Float = 4.2
let myString = "forty-two"

let wrappedInt = SomeWrapper(myInt)       // T inferred as "Int"
let wrappedFloat = SomeWrapper(myFloat)   // T inferred as "Float"
let wrappedString = SomeWrapper(myString) // T ingerred as "String"

print(wrappedInt.dynamicType)    // SomeWrapper<Int>
print(wrappedFloat.dynamicType)  // SomeWrapper<Float>
print(wrappedString.dynamicType) // SomeWrapper<String>

You can naturally write generic functions allowing arguments for SomeWrapper<T> instances, type constraining T in the same fashion as in the struct definition above

func foo<T: MyGenericTypes>(bar: SomeWrapper<T>) -> () {
    print(bar.value)
}

foo(wrappedInt)    // 4.2
foo(wrappedFloat)  // 42
foo(wrappedString) // forty-two

Upvotes: 1

Related Questions