If I know that all of my possible input objects have a certain method, but they do not share any interface, how can I declare a parameter for them in my function?


#1

Hello everyone,

I want to implement a function that input a parameter like this:

fun call(f: T) {
println(f.getName())
}

I know that all input object f will have the function getName, but I do not want create a common interface and a wrapper for each and every single one of them (there are so many), what should I do?

Thank you.

Updated:

Thank you all for your answers which are all great but still, I prefer not to use reflection since I cannot get any auto-completion. Basically what I am looking does not seem to be supported yet in Kotlin. I was just thinking that it would be great to have something like “fake interface”. For example:

fake interface HAVEMETHOD {
fun getName(): String
}

then when I call a function f that have a generic type T (<T: HAVEMETHOD>) that NOT really implements that interface, I know that in f, there is a method called getName(). I think that would be the most elegant way if it exists. :smiley: (but Kotlin is not perfect after all :frowning: )


#2

You have no chance with Kotlin. With Scala you could perform implicit conversion and use type classes or you could use structural typing (also known from Go). But Kotlin doesn’t offer anything like that, although there are some thoughts in the direction of structural typing.

If you don’t want to write adapters or implement a common interface, your only option is using reflection (could be dangerous with Java 9 and above, depending on your module structure).


#3

You have to use reflections, but I do not see the problem here even with Java 9+. The problem will arise only if the method is private.


#4

Thank you. Seems like there is really no easy way.


#5

Well you could structure your code in a different way (although this is not always possible and probably leads to different problems) but as @darksnake said, reflection should solve this problem without many problems. In that case the biggest downside is that the compiler can no longer check if you pass a valid type.


#6

You could modify your call so it required a function for extracting the name be passed along:

fun <T> call(f: T, getName: (T) -> String) {
    println(getName(f))
}

Then, given a Person (or whatever else):

data class Person(val name: String, val age: Int)

you could call it like this:

val person: Person = TODO()

call(person, Person::name)

#7

@kevinherron Nice workaround!


#8

Reflections are not so hard. They are not optimized in compile-time though, so using reflections in general is slow and discouraged if there is another solution.The reflections call should look like that (there could be mistakes, I am writing from memory):

fun getName(obj: Any) : String?{
    return obj::class.functions.find{it.name == "getName"}?.call() as String?
}

#9

Reflective access is not only not “optimized” by the compiler, but not even checked. If an object of a type without the required method getName would be passed, the compiler wouldn’t complain. You could handle this case at runtime, of course, but such a programming style makes maintenance much harder.


#10

seems like the feature requested overhere: Implicit interfaces as in Go


#11

Or even simpler:

fun call(getName: () -> String) {
    println(getName())
}

call(person::name)

#12

This is identical to applying an interface namely: Function<T,String> - please don’t take this as critical, but it’s actually worse than applying a type interface to all classes in the hierarchy as each and every call must have this extra parameter.

What the poster wants is Duck Typing - which is exactly what compiled languages don’t give you


#13

I know how you can do this: Run kotlin as a JSR-223 script. Then you can have your Duck Typing.

The rub here is that there is no kotlin REPL available like groovysh So, you would need to bootstrap kotlin-JSR 223 in an app (which isn’t too bad) and then just blindly load/invoke your kotlin script

I am guessing, based on the simplicity of the question that this isn’t a professional pursuit where in the time required to get it right is worth the feature.

Here is the most basic implementation for loading kotlin script. Infact, it’s almost ideal as an implementation


#14

I’m well aware of what it’s called, and I was providing the OP with a workaround that they can use in Kotlin, like they asked for.

And you’re wrong that you can’t do this in static/compiled languages. Scala does this and calls it Structural Types.


#15

I guess you did take it personal after all. If you were aware that you were basically offering another form of interface typing then you could have mentioned it in your post - better articulation, perhaps. I wouldn’t have offered this solution because it actually doesn’t meet his requirements either in letter( since we now agree this actually is a form of interfacing ) or in spirit (since all invocation points now need this boilerplate and he seems against doing something tedious like re-typing everything)

I didn’t know that about Scala - I guess that’s good to know. Any others?

Numerous scripting languages offer this sort of thing: Ruby, JS, Groovy to name a few. If he bootstraps the kotlin jsr223 script engine he can write kotlin and get the duck typing he is looking for.


#16

FWIW, his “updated” text was not there at the time of my original response.

I think this post was already bikeshedded to death when I responded. Let’s let it die now…


#17

What you need is structural typing, or as many languages like for example Go says “duck-typing”.

I was once interested in this and after thinking a while about how to do this with Kotlin, I found that a static duck-typing would be most advanced, useful and compatible with the language. After some time I implemented a small prototype on GitHub.

You can see the prototype here: https://github.com/stangls/DucKtypes/

Please note that this lacks any means for automation via Gradle, Maven or IntelliJ, and it has no support and may have bugs as well as known problems (see readme).
But I think if I understand your case correctly, you can call the generator once and generate all the extension-methods for your existing classes, then drop those extension-methods which you do not need and once your code works, are safe to proceed without this duck-type prototype of mine.

Because what it does is to use reflection only once before runtime to find classes which match interfaces and creates a extension-methods for these classes which you can then simply use in your code.

It does not modify any source code, just creates one file you can inspect before using and should be compatible with any libraries you use. The nice thing is that the heavy bulk work is done before run-time at generation-time.


#18

Oh my God, you are the hero of the day :smiley: