1

I want to create a generic function with a parameter that receives the type of a class for example:

class Foo{
    var name = "Foooo"
}

class Liii{
    var name = "Liii"
}

Generic function:

fun genericFunc(objects: Any, objectType: KClass<*>) {
    print((objects as objectType).name) //This is not exist how to do this?
}

And call it like this:

val foo = Foo()
genericFun(foo, Foo::class)

val liii = Liii()
genericFun(liii, Liii::class)

In swift it exists in this way...

func genericFunc(objects: Any, objectType: Object.type) {
    print((objects as objectType).name)
}

let foo = Foo()
genericFun(foo, Foo.self)
1
  • 1
    That's not legal swift. That coercion isn't guaranteed, so as would be invalid, it would need as? or as! Commented Nov 9, 2018 at 14:16

1 Answer 1

3

First of all, only Class has a .name variable. To be quite honest, I don't see the point of what you're doing here. You can just do objects::class.java.name directly if you just want the name. If you want to use KClass, you'll need to use simpleName or qualifiedName. Class also has simpleName, packageName, typeName, and canonicalName. Which also means you need to get the classs. If you absolutely want to cast it, you'll need to re-get the KClass or Class with respectively ::class or ::class.java.

Also, tiny note: I'm not sure how print works in Swift, but in Kotlin and Java, it doesn't print a new line. I'm mentioning this because I know some languages like Python have their print function work like System.out.println or println. However, print doesn't automatically create a newline.


I actually stumbled over this exact issue yesterday: If I pass a KClass to a function, I can't to whatever as kClass, because it's not found. Apparently, you can't do this. as and is assumes a class name, not an instance of Class or KClass.

Now, you have two options, both of which use generics.

The first one is still passing the class:

fun <T : Any> genericFunc(objects: Any, objectType: KClass<out T>) {
    println(objectType.java.cast(objects))

}

If you want to print the name, you have to get the class as I mentioned earlier. This is also slightly pointless, since you can just do this:

println(objects::class.java.name) 

Or if you absolutely have to cast it first (though I recommend checking with isInstance first):

println(objectType.java.cast(objects)::class.java.name)

But if the code isn't the point, let's move on.

The other is using reified types. Here you can use as:

inline fun <reified T : Any> genericFunc(objects: Any) {
    print(objects as T)
}

The last one is called differently:

genericFunc<SomeClass>(instance);

However; this isn't safe. I highly recommend you check types first. For the first one, use objectType.isInstance(objects), for the second you can just use is. If you don't, you risk getting a ClassCastException if the type doesn't match.

Also, depending on what you're planning to do with it, you could also use generics entirely:

fun <T> genericFunc(objects: T) {
    // Do whatever
}

Optionally with constraints for the generic type.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.