Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift custom type conversion by using `as` keyword

Tags:

swift

for example, I have two classes, named ClassOne and ClassTwo:

open class ClassOne {
    open var id: String?
    public init(id: String?) {
        self.id = id
    }
}

open class ClassTwo {
    open var id: String?
    open var title: String?
    public init(id: String?, title: String?) {
        self.id = id
        self.title = title
    }
}

then, create some instances:

let one = ClassOne(id: "1")

now, how to convert one to ClassTwo type by using one as classTwo?

I know I can implement a function like public init(classOne: ClassOne) {}, but I just wondering 'how to use as on custom types?'

I noticed something called _ObjectiveCBridgeable, is there anything similar for pure swift types?

like image 250
Meniny Avatar asked Mar 17 '26 00:03

Meniny


2 Answers

You don't, or rather, Swift can't.
(But in C++ on the other hand, you just need to create a constructor which takes the other type as parameter, and said constructor is called automatically (unless marked explicit).)

Your classes are not related in any way, programmatically speaking, however you have several solutions. For example:

Solution #1: Convert

You could add an init method to your ClassTwo, that takes a class one instance as a parameter.

convenience init(classOne:ClassOne) {
    self.id = classOne.id
    self.title = nil
}

You could also just have a non-init method that would do the same thing.

Solution #2: Subclass

Make ClassTwo a subclass of ClassOne

open class ClassTwo : ClassOne {
    open var title: String?
    public init(id: String?, title: String?) {
        super.init(id:id)
        self.title = title
    }
}

And now you'd see that you can use it interchangeably (but note that this can cause some headaches sometimes aswell):

func funcThatTakesA(classOne:ClassOne) {
}

let one = ClassOne(id: "1")
let two = ClassTwo(id: "id", title: "Instance")

funcThatTakesA(classOne: one)
funcThatTakesA(classOne: two) //It works!
like image 71
Yoam Farges Avatar answered Mar 19 '26 20:03

Yoam Farges


No: they are unrelated types (even if on the surface, they share a similar internal layout).

Even if it were C structs, you force-casted a pointer of one stype into a pointer of the other, and padding/alignment were such that the "common" member id had the exact same memory layout (same type and offset from start address of the object) in instances of both types, the second member title would certainly lie outside bounds!

Swift is very strict regarding types. In your particular case, you should either:

  • Have both unrelated classes conform to a protocol that requires a property id of type String?

  • Have ClassTwo inherit from ClassOne.

...and yet, either of these approaches will only let you cast an instance of ClassTwo into one of ClassOne, not viceversa (storage for the extra property title can not be magically synthesized by the cast).

like image 29
Nicolas Miari Avatar answered Mar 19 '26 19:03

Nicolas Miari



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!