3

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?

Meniny
  • 660
  • 8
  • 22
  • Do you mean *"custom type **conversion**"* ? – That are two unrelated types, there is no `as` conversion between them. – Martin R Aug 18 '17 at 07:09
  • @MartinR yes, unrelated, but i'm wondering if I can implement some thing to convert them – Meniny Aug 18 '17 at 07:10
  • 2
    And what would you expect that `(one as ClassTwo).title` evaluates to? – Martin R Aug 18 '17 at 07:13
  • @MartinR maybe the `id` in `ClassOne, or `nil`. like `String` and `NSString`, they all have some thing special and unique, but `"string" as NSString` does works – Meniny Aug 18 '17 at 07:22
  • 1
    "string" as NSString is *bridging* between Swift and Objective-C types, see https://stackoverflow.com/questions/35893517/is-it-possible-to-replicate-swifts-automatic-numeric-value-bridging-to-foundatio on how that can be replicated for other types (using "hidden" protocols). – Very early Swift versions allowed to define custom conversions between arbitrary types, that feature has been removed long ago. – Martin R Aug 18 '17 at 07:28
  • Using type conversion between unrelated types doesn't make sense. – 思齐省身躬行 Aug 18 '17 at 08:13
  • @user5685969 yes, that's right. but this is just an example. What I'm asking here is how to use `as` on custom types to convert instances. – Meniny Aug 18 '17 at 08:16
  • @MartinR thanks a lot – Meniny Aug 18 '17 at 08:16

3 Answers3

3

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!
Top-Master
  • 7,611
  • 5
  • 39
  • 71
Yoam Farges
  • 773
  • 4
  • 16
1

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).

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
0

Basically, There is no relation between them so, first of all, you have to make the relationship in between two classes: Here we show with the help of inheritance:

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

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

let one = ClassOne(id:"hello") as? ClassTwo
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Salman Ghumsani
  • 3,647
  • 2
  • 21
  • 34