2

I have some data transfer class which I want to share between platforms. There is only one difference. The implementations have different annotations on different platforms. What is the best way to do it? I know the only one way.

In the commonsMain:

expect class ErrorMessage (message: String = "") : DataTransferObject {
    var message: String
}

In jvmMain:

@SomeJvmAnnotation
actual class ErrorMessage actual constructor (actual var message: String) : DataTransferObject

But if I implement every class this way than there is no profit from KMM. This way I need to implement every class n + 1 times where n is a number of platforms. Is there a simpler way to apply different annotations?

May be there is a way not to put expect on class.

1 Answers1

2

Not the greatest solution, but you can use actual and expect to define your platform-specific annotations.

I used it to ignore unit tests only on the JS runtime.

commonMain

 ​/*​* 
 ​ * Ignore a test when running the test on a JavaScript test runtime. 
 ​ ​*/ 
 ​@Target( ​AnnotationTarget​.​CLASS​, ​AnnotationTarget​.​FUNCTION​ ) 
 ​expect​ ​annotation​ ​class​ ​JsIgnore​()

jsMain

 ​actual​ ​typealias​ ​JsIgnore​ ​=​ kotlin.test.​Ignore

jvmMain

 ​// Nothing to do. This should only ignore tests on the JavaScript test runtime. 
 ​actual​ ​annotation​ ​class​ ​JsIgnore

I guess whether or not this is appropriate for you will really depend on the specific annotations you need for each platform, and to which degree they semantically overlap.

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161
  • 1
    Correct me if I'm wrong. I can follow your advice only if the annotations on different platforms have the same arguments. If at least one argument is different your advice won't work. Actually I've tried to write such an annotation. But I've failed on the jvm plavform. In java there is a vararg String parameter, If I try to write vararg String parameter in Kotlin it becomes Array. The error appears becouse java vararg parameter is Array. I've tried to use Array instead of vararg in Kotlin, but it is also considered as different type. So I've completely failed. – Vitaliy Tsirkunov Jan 16 '22 at 10:54
  • As to your first question: yes, if the annotation has parameters it's even more complicated. But, you can still do what I do in the example, essentially adding all annotations for all platforms, at least if there are no platform-specific parameters. You simply ignore the annotations destined for the other platform in the actual implementations (hence the `Js` prefix). Your second follow-up question seems more suitable to post as a new question with a bit more detail. – Steven Jeuris Jan 16 '22 at 11:26