I`m new at kotlin and want to build a multiplatform application.
For the common part I want to use data classes that contains platform specific functions.
Is it possible to use the kotlin data class in a platform specific declaration?
something like
expect data class Foo(val bar: String)
best regards
From Kotlin's docs on Platform Specific Declarations:
Expected declarations never contain any implementation code.
Since data classes generate implementations they can't be used in expect declarations. The actual implementation can be a data class since it does not change the semantics of the declared class.
expect class Some {}
actual data class Some(val test: UUID)
Related
When I define an enum class in Kotlin
enum class Answer {
YES,
NO
}
It has a valueOf(value: String) attached to it.
val doYouWantBeerOrCoffee = Answer.valueOf("YES") // Answer.YES
But where is this function actually defined? It is definitely not in the Enum.Kt and using Idea's Go to Implementation tool only takes me back to my Answer enum definition.
It's generated by the compiler. That's what "synthetic" means in
Enum classes in Kotlin have synthetic methods allowing to list the defined enum constants and to get an enum constant by its name.
If you decompile Answer.class you'll see it, but it isn't written as Kotlin (or Java) source code anywhere.
This method is a part of JDK, and defined in Enum.java class.
Which is the common base class of all Java language enumeration types.
Kotlin uses the same class for enums
Data classes print out just fine in MPP projects. When I toString() the KClass object for my class, I get:
class com.example.MySimpleClass (Kotlin reflection is not available)
How Can I do what data class does and have a nice clean name without reflection?
I don't have it set up myself to test, so answer is based purely on documentation:
KClass.simpleName is available in Common code; qualifiedName isn't, but since 1.3 it is on every platform, so you could define an expect fun in your multiplatform part and make all actual implementations access qualifiedName.
I have access to a library, but I don't want to fork the code and maintain the library, because I am too new to Kotlin.
The code looks like this:
data class Foo<out T: Baz>(val foos: ..., bars: ...)
I can call methods from the library to get back a Foo, but I need that Foo to implement Serializable from java.io. I asked someone how might I do this, and they suggested that I extend from the data class. Is this the right course of action, and if so, how might one go about it?
In Kotlin you can't make class implement interface which it doesn't implement (unlike Haskell and Go).
Sore your options are folowing:
Create your own class implementing Serializable which has all the same fields as basic. Then you can even create constructor in new class which accepts basic class as argument
Use another way of serialization, for example kotlinx.serialization
I noticed that some functions for coroutines are marked with actual keyword.
From documentation:
actual denotes a platform-specific implementation in multiplatform
projects
As I understood from documentation actual keyword is used for multiplatform projects and should work in pair with expect keyword.
Something like this:
Common module:
package org.jetbrains.foo
expect class Foo(bar: String) {
fun frob()
}
fun main(args: Array<String>) {
Foo("Hello").frob()
}
Corresponding module:
package org.jetbrains.foo
actual class Foo actual constructor(val bar: String) {
actual fun frob() {
println("Frobbing the $bar")
}
}
That case is clear.
But in package kotlinx.coroutines.experimental I noticed that some functions like launch or withContext are marked as actual but there are no expect functions in package.
So what is the purpose of actual keyword without expect?
The kotlinx.coroutines library actually makes use of multiplatform projects since it supports both the JVM and JS compilation targets.
You can find the common module here, and the specific expect declarations for the functions you've mentioned here.
While the source code in the other answer helped, I found this page (linked off of the page #jim-andreas mentioned in the comments above) was much more helpful.
Specifically, this passage:
If you're developing a multiplatform application that needs to access platform-specific APIs that implement the required functionality (for example, generating a UUID), use the Kotlin mechanism of expected and actual declarations.
With this mechanism, a common source set defines an expected
declaration, and platform source sets must provide the actual
declaration that corresponds to the expected declaration. This works
for most Kotlin declarations, such as functions, classes, interfaces,
enumerations, properties, and annotations.
The compiler ensures that every declaration marked with the expect keyword in the common module has the corresponding declarations marked with the actual keyword in all platform modules. The IDE provides tools that help you create the missing actual declarations.
Again, for more information, you can visit this page.
I'd like to write a plugin for Intellij IDEA that should modify a Java and Kotlin code.
I use the method
PsiClass.getMethods()
in order to get all methods of Java and Kotlin classes. So far so good, so then I use methods like
PsiClass.add(), PsiClass.addAfter(), PsiClass.addBefore()
that all work fine once they are called on Java files, but start to throw an exception
IncorrectOperationException
once I called them on a Kotlin class.
I'd appreciate any hint on how I can modify Kotlin and Java classes (preferably using the same approach).
When you search for a Kotlin class via the JavaPsiFacade, it returns the light class which is a shallow representation that is just based on the information in the class file. In order to add PSI elements, you have to call navigationElement on it. Then, IJ will parse the source and build a full PSI tree that can be modified.
However, if the class is a Kotlin class, navigationElement will return a KtClass which is not derived from PsiClass. You will have to use the facilities in the Kotlin hierarchy to modify it. Method instances in Kotlin are also not instances of PsiMethod, but instances of KtMethod.
For analyzing Java and Kotlin sources in a common fashion there is a different syntax tree called "UAST", but for modifications you need a language-specific approach.