0

So I walk against this problem.

I have a BaseModel with some variables inside and a few normal "final" Models that inherit from the BaseModel.

If I have an array with class BaseModel with inside a few final models, and then loop trough those models and sent them to a function that uses generics. And check the class of the generics I get back they are from class BaseModel instead of the final class model that I need. How can I retrieve in a dynamic way the class of the final model. And of course I could cast them, but I would love to find a better solution.

See example in the playground I made:

import UIKit

class BaseModel {

    var id: Int

    init(id: Int) {
        self.id = id
    }
}

final class PersonModel: BaseModel {

    var firstName: String
    var surname: String

    init(id: Int, firstName: String, surname:String) {

        self.firstName = firstName
        self.surname = surname

        super.init(id: id)
    }
}

func genericsTest<C: BaseModel>(with object: C) {
    print("Class type: \(C.self)")
}

var person0 = PersonModel(id: 0, firstName: "John", surname: "Doe")

genericsTest(with: person0)
// This prints: "Class type: PersonModel"

var person1 = PersonModel(id: 1, firstName: "John1", surname: "Doe")
var person2 = PersonModel(id: 2, firstName: "John2", surname: "Doe")
var person3 = PersonModel(id: 3, firstName: "John3", surname: "Doe")

var personArray: [BaseModel] = [person0, person1, person2, person3]

for person in personArray {
    print("Class type in for loop: \(person.self)")
    // This prints: "Class type in for loop: __lldb_expr_195.PersonModel"
    genericsTest(with: person)
    // This prints: "Class type: BaseModel"
}

So in the for loop if I print the object.self I get the class I expect but in the function with generics do the same call I get the base class.

Edit 1:

So if it would be possible to make Generic C the type of the final model I would be able to create thing like:

func genericsTest<C: BaseModel>(with type: C.Type, and object: C) {
    let test = KeyPath<C, Int>
}

Just as example

Jippe Joosten
  • 403
  • 1
  • 3
  • 16
  • Did you perhaps mean `func genericsTest(with object: C) { print("Class type: \(object.self)") }` – vacawama Jul 06 '17 at 11:19
  • So I would like C to be the class of the final model. – Jippe Joosten Jul 06 '17 at 11:21
  • @vacawama `object.self` is equivalent to just `object`. Postfix `.self` on an expression just returns that expression (I'm not even sure why Swift has it tbh). OP almost certainly just wants `type(of: object)`. – Hamish Jul 06 '17 at 11:25
  • I added a example of what would be possible if I could make the generic C the class of the final model instead of the base model. – Jippe Joosten Jul 06 '17 at 11:29
  • 1
    `C` *is* `BaseModel` when called from the array loop. You can get the actual type with `type(of: object)` – Martin R Jul 06 '17 at 11:32
  • @MartinR But I can't do KeyPath so I would like to know a way to get the C in the function genericsTest to be the type I need – Jippe Joosten Jul 06 '17 at 11:39
  • @JippeJoosten But the dynamic type of `object` isn't known until runtime, so it doesn't make sense to use it in a static type. What exactly are you trying to achieve with your keypath here? – Hamish Jul 06 '17 at 11:47
  • @Hamish So I have an array of AnyKeyPath that I have to cast to KeyPath so I thought if I create a function with generics that contains the type of the class so it would be KeyPath – Jippe Joosten Jul 06 '17 at 12:07

1 Answers1

0

Have a look at this Question

You define a array of type 'BaseModel' so in your for loop it basically is saying

for let person: BaseModel in personArray

Making person of type BaseModel

In the function:

func genericsTest<C: BaseModel>(with object: C) {
    print("Class type: \(C.self)")
}

You are using the type, in contrary in this code:

print("Class type in for loop: \(model.self)")

You are using the object. If you change the C to object you will get the same result.

Do remember if you going to use this in you project to determine what type of object this is. You need to seriously go back to your drawing board. Because this is not OOP!

Stornu2
  • 2,284
  • 3
  • 27
  • 47
Ian van Wijk
  • 159
  • 2
  • 8
  • But if I print person it gives me "__lldb_expr_195.PersonModel" back so it knows it is a PersonModel in the array. And now I would like to know a way to make the genericsTest functions also to know this in the generic type C – Jippe Joosten Jul 06 '17 at 11:40
  • You mean this line: genericsTest(with: person0) – Ian van Wijk Jul 06 '17 at 11:41
  • No in the for loop I print the object person and it gives me "__lldb_expr_195.PersonModel" back. exactly the same as when I do print(person0) some where in the code. But how can I make it so in the for loop it does the same as this line: genericsTest(with: person0) without casting it. – Jippe Joosten Jul 06 '17 at 11:47