Extension function collision [duplicate] - kotlin

If I have a jar, on the classpath, where I've created an extension function on say the String class for argument's sake and I have another jar with the same extension function on String, how will Kotlin resolve the two?
I presume if both functions are defined in the same packages then there will be a clash?
But if different packages, how I can distinguish the two extensions?

Indeed, if they're in the same package, it won't compile. For the other scenario, let's say you have two files with two different packages, containing extension functions with the same signature:
First file:
package ext1
fun Int.print() = print(this)
Second file:
package ext2
fun Int.print() = print(this * 2)
And this file where you're trying to use it:
package main
fun main(args: Array<String>) {
42.print()
}
IntelliJ will actually give you an import dialog where you can choose which one you want to use:
You can import one of them like this:
import ext1.print
And if you need to use the other one as well, you can rename it with the as keyword. This keyword works for imports in general, classes with the same name, etc.
import ext2.print as print2
So this program compiles and prints 4284:
package main
import ext1.print
import ext2.print as print2
fun main(args: Array<String>) {
42.print()
42.print2()
}
As a quick note, the one you import with the as keyword will be slightly harder to use, as autocomplete doesn't seem to pick it up well, selecting the second option here just completes the call to 42.print().

So since extension function in kotlin is just static function, other functions will be distinguish by import.
Also you can make alias for one of extension functions for more readability:
import by.bkug.extensions.helpers.extension
import by.bkug.extensions.extension as extension1
fun test() {
myType().extension() // by.bkug.extensions.helpers.extension
myType().extention1() // by.bkug.extensions.extension
}

Related

Remove import when using Kotlin's #Deprecated "ReplaceWith" annotation

I have a custom function MutableStateFlow.update(), which i want to deprecate in favor of the official "kotlinx.coroutines.flow.update" version.
#Deprecated(
message = "This is not thread safe. Use the official version from kotlinx.coroutines.flow.update",
ReplaceWith("update(transformation)", "kotlinx.coroutines.flow.update"),
DeprecationLevel.ERROR
)
public inline fun <T> MutableStateFlow<T>.update(transformation: (previousValue: T) -> T) {
value = transformation(value)
}
This works ok-ish:
The main issue is that the signature of the old & the new fun are the same, so the IDE gets confused which to choose, since both are imported.
I therefore need to remove the import for my old version when the ReplaceWith is called. Is this possible? (Is there a better alternative?)
In case it matters: We're working mainly with Android Studio
If this is all in one open project, you could Refactor->Rename your update function (Shift + F6) to some unique name. Then there won't be the import conflict.

Kotlin script: main function does not get called locally, unlike in online judge

I am trying to participate in online Codeforces contests using Kotlin.
My understanding is I should use Kotlin script if my code is contained within a single file.
If I run the following file locally (version 1.6.10):
kotlin just_main.main.kts
// just_main.main.kts
fun main() {
println("Hello World")
}
Nothing happens. I need to add an explicit call for it to actually execute main:
// top_level_call.main.kts
fun main() {
println("Hello World")
}
main()
So far, so normal. The problem occurs when I try to submit my solution to the Codeforces online judge. The judge expects no top-level code and runs the main function instead. So just_main runs fine, but top_level_call produces a compilation error:
Can't compile file:
program.kt:43:1: error: expecting a top level declaration
main()
^
This leads to the awkward situation of me having to add the main() call when I want to try my solution locally, but having to remove it every time I upload an attempt.
Is there a way to have my local Kotlin behave the same as the online judge, meaning implicitly running any main functions (meaning just_main would produce output)?
I haven't found a way to do this with Kotlin script files, but you can also use normal .kt files without having any classes in the file (my understanding is that Kotlin magically turns them into Java class bytecode/files):
kotlinc a.kt && kotlin AKt < a.in
This "runs" a.kt with standard input from a.in.
(And yes I only found this after I already wrote the question)

Kotlin unresolved reference to local package

File ./Main.kt:
import numbers
fun main() {
var value = numbers.sum(7, 4)
}
File ./numbers/Operations.kt:
package numbers
fun sum(val1: Int, val2: Int): Int {
return val1 + val2
}
Running the command kotlinc Main.kt outputs:
Main.kt:1:8: error: unresolved reference: numbers
import numbers
Main.kt:4:17: error: unresolved reference: numbers
var value = numbers.sum(2, 3)
If I try to add import java (I am new in Kotlin ans I saw someone imported this. I thought it is a part of a standard library) then output also contains:
Main.kt:1:8: error: packages cannot be imported
import java
What I did wrong?
SOLUTION (Thanks to #gidds):
Was need to pass each file to the complier, not like with Java compiler (javac)
kotlinc Main.kt numbers/Operations.kt
numbers is a package.  And, as the error says, packages cannot be imported.  Only classes, functions, or properties.
If you import numbers.sum, you should find you can call it with e.g. sum(7, 4).
Or you could call its fully-qualified name directly, without the import: numbers.sum(7, 4).
It's the same with java, which is also a package.  You can import java.util.concurrent.ConcurrentHashMap (a class), but not java, java.util, nor java.util.concurrent (which are all packages).  (Java has the same restriction.)

function min in Kotlin

i use the Mathematical function "min" in my Kotlin code to declare a variable "toRemove"
val toRemove = min(preferredQuantity - taken, stock.quantity)
error message : Kotlin unresolved reference
1/ may i know how could i solve it?
2/ the function is within kotlin.math, why I cannot use it directly?
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/
Thanks!
For completeness' sake: as pointed out by #Tenfour04 in the comments, make sure that kotlin.math.min is imported by checking that one of
import kotlin.math.min
import kotlin.math.*
is on top of the file. The kotlin.math.* variant will import everything from the kotlin.math package. See the Kotlin documentation page on imports.

Is there a way to suppress Kotlin's default import?

Is there a way to suppress (e.g., via a commnad line flag passed to the compiler) Kotlin's default import of multiple packages? or - alternatively - to be selective about it?
This is easy, just use your alternative to replace it by using as, and the default import will be replaced by your one.
Here's a simple example, if you want to use java.lang.String instead of kotlin.String, although it's not recommended, this is just an example.
import java.lang.String as String
// here, String is not `kotlin.String`.
private fun main(vararg args: String) {
}
BTW there's a trick about refactoring, like if you want to replace all Any used in a file with java.lang.Object, put this after the package declaration:
import java.lang.Object as Any
And the implicit import to Any is suppressed and superseded by Object.