i am a Java Android Developer and i'm approaching to Kotlin
I have defined the following class:
open class Player : RealmObject() {
...
}
And i defined the following two extensions, one for the generic RealmObject class and one for the specific Player class:
fun RealmObject.store() {
Realm.getDefaultInstance().use { realm ->
realm.beginTransaction()
realm.copyToRealmOrUpdate(this)
realm.commitTransaction()
}
}
fun Player.store(){
this.loggedAt = Date()
(this as RealmObject).store()
}
What i want is if i call .store() on any RealmObject object, the RelamObject.store() extension will be called BUT if i call .store() on a Player instance the extension that will be called will be Player.store().
(No problem for now)
I don't want to copy paste the same code, i love to write less reuse more.
So i need that internally the Player.store() will call the generic RealmObject.store()
I got it. The code i wrote up there is actually working as expected :D
What i am asking is (just because i wrote that just by personally intuition):
Is this the good way?! Or there is some better way?
Thank you
Your approach seems to be perfectly correct, because it does exactly what is needed. Kotlin resolves the extension calls based on the static (inferred or declared) type of the receiver expression, and the cast (this as RealmObject) makes the static expression type RealmObject.
Another valid way to do this, which I'm not sure is better, is to use a callable reference to the other extension:
fun Player.store(){
this.loggedAt = Date()
(RealmObject::store)(this)
}
Related
I'm using kotlin sealed class. And I need to retrieve specific subclass. My sealed class:
sealed class Course(
val type: Type
) {
data class ProgrammingCourse(val name: String, val detail: String) : Course(Type.PROGRAMMING)
object LanguageCourse: Course(Type.LANGUAGE)
.....
}
For example I have function which can return Course:
fun getCourse(): Course {
if(...)
return Course.ProgrammingCourse("test", "test")
else
return Course.LanguageCourse
}
In addition, I have a method that can only work with a specific subclass of the Course class. Fox example:
fun workWithCourse(course: Course.ProgrammingCourse) {
// here some logic
}
And now I'm trying to get the course using the method getCourse(), and then pass it to the method workWithCourse()
fun main() {
val course = getCourse()
workWithCourse(course)
}
Error:
Type mismatch.
Required:
Course.ProgrammingCourse
Found:
Course
But I know the course type - Type, parameter that each course has. Can I, knowing this Type, cast the course (which I retrieve from getCourse() method) to a specific subclass ? Is there such a way ?
Please help me
P.S.
I don't need type checks like:
if(course is Course.ProgrammingCourse) {
workWithCourse(course)
}
I need the subclass to be automatically inferred by the Type parameter, if possible.
P.S.2
The need for such a solution is that I have a class that takes a Course, it doesn't know anything about a particular course, at the same time the class takes the Type that I want to use for identification. This class also receives an interface (by DI) for working with courses, a specific implementation of the interface is provided by the dagger(multibinding) by key, where I have the Type as the key. In the same way I want to pass by the same parameter Type specific subclass of my Course to my interface which working with specific courses.
No, there is no way for automatic inference to the best of my knowledge.
You returned a Course, and that's what you have. Being sealed here does not matter at all. Generally what you do here is use the when expression if you want to statically do different things depending on the type, but if it's just one type (ProgrammingCourse) that can be passed to workWithCourse, then an if is probably right, with dispatch using as.
That said, this looks like counter-productive design. If you can only work with one course, why do they even share a top level interface? The way the code is written implies working is a function that can take any course, or should be a method member. Anything else is very confusing. Perhaps workWithCourse should take a Course and use the when expression to dispatch it appropriately?
In kotlin you can specify the class explicitly with as.
val course = getCourse()
if (type == Type.PROGRAMMING) {
workWithCourse(course as Course.ProgrammingCourse)
}
*thanks Joffrey for his comment
What you seem to be asking for is a compile-time guarantee for something that will only be known at runtime. You didn't share the condition used in getCourse(), but in general it could return both types.
Therefore, you need to decide what will happen in both cases - that's not something the compiler can decide for you via any "inference".
If you want the program to throw an exception when getCourse() returns something else than a Course.ProgrammingCourse, you can cast the returned value using as:
val course = getCourse() as Course.ProgrammingCourse
workWithCourse(course)
If you don't want to crash, but you only want to call workWithCourse in some cases, then you need an if or when statement to express that choice. For instance, to call it only when the value is of type Course.ProgrammingCourse, then you would write the code you already know:
if (course is Course.ProgrammingCourse) {
workWithCourse(course)
}
Or with a when statement:
val course = getCourse()
when (course) {
is Course.ProgrammingCourse -> workWithCourse(course)
is Course.LanguageCourse -> TODO("do something with the other value")
}
The when is better IMO because it forces you (or other devs in the team) to take a look at this when whenever you (or they) add a new subclass of the sealed class. It's easy to forget with an if.
You can also decide to not test the actual type, and focus on the type property like in #grigory-panov's answer, but that is brittle because it relies on an implicit relationship between the type property and the actual type of the value:
val course = getCourse()
if (type == Type.PROGRAMMING) {
workWithCourse(course as Course.ProgrammingCourse)
}
The main point of using sealed classes is so you can use their actual type instead of a manually managed type property + casts. So I'd say use only is X and don't set a type property at all. Using a sealed class allows Kotlin to type-check a bunch of things, it's more powerful than using such a property.
In Java, we can create an utilities class like this:
final class Utils {
public static boolean foo() {
return false;
}
}
But how to do this in Kotlin?
I try using functions inside object:
object Utils {
fun foo(): Boolean {
return false
}
}
But when call this method from Java code it need to add INSTANCE. Ex: Utils.INSTANCE.foo().
Then I change to declare it as top-level function (without class or object):
#file:JvmName("Utils")
#file:JvmMultifileClass
fun foo(): Boolean {
return true
}
Then I can call Utils.foo() from Java code. But from Kotlin code I got Unresolved reference compiler error. It only allow be to use foo() function directly (without Utils prefix).
So what is the best approach for declaring utils class in Kotlin?
The last solution you've proposed is actually quite idiomatic in Kotlin - there's no need to scope your function inside anything, top level functions are just fine to use for utilities, in fact, that's what most of the standard library consists of.
You've used the #JvmName annotation the right way too, that's exactly how you're supposed to make these top level functions easily callable for Java users.
Note that you only need #JvmMultifileClass if you are putting your top level functions in different files but still want them to end up grouped in the same class file (again, only for Java users). If you only have one file, or you're giving different names per file, you don't need this annotation.
If for some reason you want the same Utils.foo() syntax in both Java and Kotlin, the solution with an object and then #JvmStatic per method is the way to do that, as already shown by #marianosimone in this answer.
You'd need to use #JvmStatic for that:
In Kotlin:
object Utils {
#JvmStatic
fun foo(): Boolean = true
}
val test = Utils.foo()
In Java:
final boolean test = Utils.foo()
Note that the util class you used in Java was the only way to supply additional functions there, for anything that did not belong to a particular type or object. Using object for that in Kotlin does not make any sense. It isn't a singleton, right?
The second approach you mentioned is rather the way to go for utility functions. Internally such functions get translated to static ones and as you can see they become the static util classes in Java you are searching for, as you can't have standalone functions in Java without a class or enum. In Kotlin itself however they are just functions.
Some even count utility classes to the anti-patterns. Functions on the other hand make totally sense without a class or object whose name hasn't so much meaning anyway.
I am aware that extension functions are used in Kotlin to extend the functionality of a class (for example, one from a library or API).
However, is there any advantage, in terms of code readability/structure, by using extension functions:
class Foo { ... }
fun Foo.bar() {
// Some stuff
}
As opposed to member functions:
class Foo {
...
fun bar() {
// Some stuff
}
}
?
Is there a recommended practice?
When to use member functions
You should use member functions if all of the following apply:
The code is written originally in Kotlin
You can modify the code
The method makes sense to be able to use from any other code
When to use extension functions
You should use extension functions if any of the following apply:
The code was originally written in Java and you want to add methods written in Kotlin
You cannot change the original code
You want a special function that only makes sense for a particular part of the code
Why?
Generally, member functions are easier to find than extension functions, as they are guaranteed to be in the class they are a member of (or a super class/interface).
They also do not need to be imported into all of the code that uses them.
From my point of view, there are two compelling reasons to use extension functions:
To "extend" the behaviour of a class you're not the author of / can't change (and where inheritance doesn't make sense or isn't possible).
To provide a scope for particular functionality. For example, an extension function may be declared as a freestanding function, in which case it's usable everywhere. Or you may choose to declare it as a (private) member function of another class, in which case it's only usable from inside that class.
It sounds like #1 isn't a concern in your case, so it's really more down to #2.
Extension functions are similar to those you create as a utility functions.
A basic example would be something like this:
// Strings.kt
fun String.isEmail() : Boolean {
// check for email pattern and return true/false
}
This code can be written as a utility function in Java like this:
class StringUtils {
public static boolean isEmail(String email) {
// check for email pattern and return true/false
}
}
So what it essentially does is, calling the same function with the object you call on will be passed as the first parameter to the argument. Like the same function I have given example of in Java.
If you want to call the extension function created in kotlin from java, you need to pass the caller as the first argument. Like,
StringsKt.isEmail("example#example.com")
As per the documentation,
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.
They are simply static functions with the caller as the first argument and other parameters followed by it. It just extends the ability for us to write it that way.
When to create extension functions?
When you don't have access to that class. When that class belongs to some library you have not created.
For primitive types. Int, Float, String, etc.
The another reason for using extension function is, you don't have to extend that class in order to use the methods, as if they belong to that class (but not actually part of that class).
Hope it makes a bit clear for you..
As mentioned in other answers, extension functions are primarily used in code that you can't change - maybe you want to change complex expression around some library object into easier and more readable expression.
My take would be to use extension functions for data classes. My reasoning is purely philosophical, data classes should be used only as data carriers, they shouldn't carry state and by themselves shouldn't do anything. That's why I think you should use extension function in case you need to write a function around data class.
I'm a beginner of Kotlin, there are many omitted code with Kotlin. It make me crash when I read some sample code.
Such as var map=HashMap()
I can't judge what HashMap() is function or class. I have to judge it by Hint of Android Studio. Do you have a simple way?
If I use java, it will be different code style.
Function: Map map=myFunction()
Class: Class myClass=new Class()
First, if you follow Java naming conversion, class is PascalCase and function is camelCase.
Second, it does not matter. Creating a new object is just a constructor returning an object. It does not different from a a function return an object.
I can't judge what HashMap() is function or class
Don't think of this as class or function. HashMap() is a constructor which is really a method (function) that returns an instance of an object. So there is really no need of the new keyword here, and it make for clean code.
You can identify if it's a function or a constructor based on the Name itself (the case of the name).
I have next code in kotlin:
handler.postDelayed(object : Runnable {
override fun run() {
Timber.i("run post msg")
handler.postDelayed(this, AppPrefs.SEARCH_DELAY)
}
},AppPrefs.SOCKET_INTERVAL)
how you see it's simple standard way to create delayed task (with Runnable class). Value this references to anonimus Object implements Runnable and compile and works fine
But when i make lamdba for this:
handler.postDelayed({
Timber.i("run post msg")
handler.postDelayed(this, AppPrefs.SOCKET_INTERVAL)
},AppPrefs.SOCKET_INTERVAL)
value this referenced to outher class.
How referenced from inner anonimus class to yourself?
You cannot do this. A similar question was asked on Kotlin's forum and yole (one of the creators of the language) said this:
this in a lambda refers to the instance of the containing class, if any. A lambda is conceptually a function, not a class, so there is no such thing as a lambda instance to which this could refer.
The fact that a lambda can be converted into an instance of a SAM interface does not change this. Having this in a lambda mean different things depending on whether the lambda gets SAM-converted would be extremely confusing.