I found an interesting code when reviewing my colleague’s code these days, and I wrote it into the corresponding pseudocode as follows:

class UserViewModel(val userUsecase: UserUsecase) {

    // Get userName according to userId
    fun getUser(userId:Int) {
        val name = userUsecase(userId).name
    }
    
}

class User(val name: String.val age: Int) {}
Copy the code

In Kotlin, object initialization can omit the new operator, that is, the class is followed by a (), why an initialized object can continue to use (), intuitive feeling, I thought it was an initialized object, The only thing that doesn’t feel like an initialization to me is that userUsecase doesn’t start with a capital case, which makes me think it’s an initializer.

If I wanted to click on it to see how I was getting a User based on userId, no matter how I traced the code, I couldn’t go to the actual logical code call, clicking on userUsecase would go directly to the constructor of UserViewModel, clicking on Name would go to the User object, It bothers me.

I had to click on the UserUsecase class to see the code, which was a disaster for the Review people, but in order to solve the problem, compromise and find out.

Enter the UserUsecase class with the following pseudocode:

class UserUsecase {
    operator fun invoke(userId: Int): User {
        // Get User data from the database by id
        // Return User data
        return User("lisi".30)}}Copy the code

After seeing the strange invoke function and using the operator overload, I looked up the syntax on Kotlin’s Chinese websiteCall operatorIt is explained in the chapter: Object ()Is equivalent toObject. The invoke ()(a)Where is the parameter of the function, that is, the code above can be translated:

class UserViewModel(val userUsecase: UserUsecase) {
    fun getUser(a) {
        val name = userUsecase(1001).name
        / / equivalent to the
        val name2 = userUsecase.invoke(1001).name
    }
}
Copy the code

You can also use Kotlin Decompile to look at the results:

Note that object () is written conditionally:

  • The operator modifier method must be used
  • The method name must be Invoke
  • The Invoke parameter can be multiple without limitation

Since the Invoke parameter is not limited, this creates another problem. If you overload multiple Invoke functions, you don’t know what the business side is doing when it invokes, and you still have to go into the code to know the logic.

The above example was simple enough, but in our business it was even more complicated. The Invoke function was wrapped into a parent class. When I clicked on it, I couldn’t find the Invoke function at all. The abstract method was implemented by a subclass, and I had to go back to the subclass to look at the method and finally figure out what logic the method was doing.

Conclusion:

While operator invoke can omit the function name of the caller, it is important to note that code must be defined by its class name, method name, or variable name.

I also understand people’s love for Jetpack, this writing method also appears in the official, please refer to the Domain Layer chapter. But my point is, is the process of omitting method names really necessary? Do you write code to show off your skills or to make others understand your code?