When would one prefer way 1 over way 2 or vice-ver...
# getting-started
p
When would one prefer way 1 over way 2 or vice-versa for writing function
doSomething
?
Copy code
//Way 1 (doSomething is a member function)
data class A(val item: String) {
        fun doSomething(): String{
            return item.toUpperCase()
        }
}

//Way 2 (making doSomething an extension function)
data class A(val item: String)
fun A.doSomething(): String {
        return item.toUpperCase()
 }
1
m
Way 2 will not compile, unless
this
has a
toUpperCase()
function defined somewhere. Should your extension function have
return item.toUpperCase()
?
p
Ah ! My bad, yes.. I will correct this one… thanks It is supposed to be the same function…
m
AFAIK, there is no "official" answer. My personal opinion is: do what will be easier to maintain over time. In your specific case, I would go with Way 1. If Way 2 literally had those lines in a single file, there is little advantage IMHO in the extension function, and I would use a more traditional OO style. Where Way 2 starts to get more interesting is if the class and the extension function are in separate files, and where the logic of the extension function is more tied to the file the extension function is in, not the class that it is extending. For example, suppose that
A
is really a
Customer
class, and you have some presenter / controller / viewmodel that needs to gather data from a
Customer
and prepare it for a UI or other presentation. It might be that the code "feels better" if
Customer
has certain behaviors, but that those behaviors are not general purpose ones, but are limited to the UI logic. You might implement those
Customer
behaviors as private extension functions in the viewmodel file, so the viewmodel can have the nicer syntax but those functions cannot be used elsewhere. However, this is all solely my opinion, and I expect that there are multiple patterns that other developers use. And, of course, if
A
is not your own class, but is one from a library, then extension functions are much more common, given that you cannot directly modify
A
.
a
As evidence that some people have different opinions, I've come to favor Way 2 in a great many cases, even when the extensions are in the same file. Since extensions may only access the public API of a class, this forces you into a style of very small classes with only the methods and properties that enforce internal consistency, and any features that can be implemented on top of that public API are.
It pushes you into a way of thinking where you can hold less in your head while writing extensions because you know the class itself won't let you break it 🙂
it makes things quite nice to test as well
p
Even I was slanting towards the way 1. Especially in cases when all my data class variables are not private. I do not really feel comfortable in writing an extension function which is not scoped and is readily available to the whole project. I mean as long as the function is doing something which comes in the responsibility of the class it should be okay to create a member function of it. But it feels like there is a thin line in the usages of both. I also inclined more towards way 1 due to the fact that if I were to create 2 functions with the same name for a particular data class, one inside the data class and one as an extension function, kotlin always seem to respect the member function and ignore the extension function with the same name.
1
Thank you @Mark Murphy and @Adam Powell for your answers 🙂 Gave me some useful insights indeed.
👍 2
k
I'm tending more and more towards style 2 as well, I think @Adam Powell explains it perfectly. There's a blog post about this from one of the Kotlin team leads as well: https://medium.com/@elizarov/extension-oriented-design-13f4f27deaee
💯 2
a
Good link, I enjoyed that post too 🙂
r
A big factor to use 2 is also whether or not it’s your own class.
imagine you import a contact class with name and birthdate from another library, but it misses e.g. the age. Then it’s quite handy to create an extension method.