how to copy a data class - kotlin

This is a duplicator, I want to copy the data class
data class A(
val name:String
)
data class B(
val name:String
)
class Replicator{
companion object {
fun copy(source:Any):Any?{
if(source::class.isData){
return source.copy()
}
return null
}
}
}
var copyList = arrayOf(A("1"),A("2"),B("1"),B("2")).map {
Replicator.copy(it)
}
source.copy()could not be compiled
Is there any good way to achieve it?
I have a list of data class and I need a copy of it

Related

How to change return type based on a function input which is a class name?

I have multiple data classes and each class has a corresponding class containing more info. I want to write a function in which I should be able to pass an identifier (table name corresponding to the data class). Based on this identifier, object of the corresponding class should be made, the value changed and this object should be returned as output of the function. I have written a simplified version of it on playground but I am unable to get it to work. Any help is appreciated.
class someClass(
)
class objectForSomeClass(
var value: String
)
class someOtherClass(
)
class objectForSomeOtherClass(
var value: String
)
class doSomething() {
companion object {
val classMap = mapOf(
"someClass" to objectForSomeClass::class,
"someOtherClass" to objectForSomeOtherClass::class,
)
}
// Create a map of class name to a new object based on the class name input
fun dummyFun(className: String, valueInput: String): Map<String, kotlin.Any> {
var returnObject = mutableListOf<Pair<String, kotlin.Any>>()
when(className) {
"SOME_CLASS" -> {
returnObject = mutableListOf<Pair<String, justDoIt.classMap["someClass"]()>>()
}
"SOME_OTHER_CLASS" -> {
returnObject = Map<String, justDoIt.classMap["someOtherClass"]()>
}
}
returnObject[className].value = valueInput
return returnObject
}
}
fun main() {
var obj = doSomething()
var t = obj.dummyFun("SOME_CLASS", "Value to be inserted")
// do something with t
}
Not knowing more about your classes (the ones in your code are not data classes – a data class in Kotlin is a specific type of class) I still think a lot could be simplified down to maybe even this:
fun createObject(className: String, value: String): Any? {
return when (className) {
"SomeClass" -> ObjectForSomeClass(value)
"SomeOtherClass" -> ObjectForSomeOtherClass(value)
// ...
else -> null
}
}
Additionally:
The classMap is not necessary, you can hard-code the cases in the when clause as in my example. There is also no need for reflection, which you would need to create instances from SomeType::class.
With getting rid of classMap you also do not need the companion object holding it anymore, and then you are left with one function for creating instances of your classes, and this function does not have to be in a class. You might put it into a singleton class called object in Kotlin (https://kotlinlang.org/docs/object-declarations.html#object-expressions)
Data classes in Kotlin: https://kotlinlang.org/docs/data-classes.html
You could maybe also replace each class someClass & class objectForSomeClass pair with a class someClass with a companion object.

How to figure out that class is data?

I have a data class in my project. It is very very very important to keep this class always as "data" and all his properties must be data classes too (or primitives).
Is there way to figure out programmatically that some class in project is still data-class and it consists only of data-classes which all consists of data-classes etc..?
You have to use Kotlin Reflection. You can check KClass.isData and Class.isPrimitive methods. It will be something like that I guess:
fun isSafe(kClass: KClass<*>): Boolean {
if (!(kClass.isData || kClass.java.isPrimitive)) {
return false
}
for (property in kClass.memberProperties) {
val field = property.javaField ?: continue
if (!isSafe(field.type.kotlin)) {
return false
}
}
return true
}
class Test1
data class Test2(val v: Int, private val t: Test3)
data class Test3(val v: Int, private val t: Int)
data class Test4(val t: Test1)
fun main() {
println(isSafe(Test2::class)) // print true
println(isSafe(Test4::class)) // print false
}

Wrapping data classes in kotlin

I wanted to ask about data classes in kotlin.
Suppose I have 2 data classes , data class A and data class B , I want to wrap my data class A around data class B.
Is this a case of Inheritance or inline class , I am kind of new to Kotlin .
data class A(
var x1:Float?,
var y1:Float?
)
data class B(
var x:Float?,
var y:Float?,
// other variables and methods
)
Thanks
You can't inherit a Kotlin data class from an other data class, but you can use interfaces or abstract classes and your data classes can implement/extend these:
abstract class A {
abstract var valueA: Int
}
interface B {
val valueB: Int
}
data class C(
val value2: String,
override var valueA: Int
) : A()
data class D(
override val valueB: Int,
val valueD: String
) : B

merging different models into sealed class

I’m writing PC app using Kotlin and TornadoFX.
I’ll show you what I have
FooModel.kt:
class FooModel(val id: Int){
constructor(foo: Foo) : this(foo.id)
}
Foo.kt:
data class Foo(val id: Int)
MainController.kt:
val FoosList: ObservableList<FooModel> = FXCollections.observableArrayList<FooModel>()
//bellow I wanna describe what I’m already doing with val above
fun fooDifferentOperationsForExample(example: Int){
example1Object = FoosList.find{ it.id == example }
example2Object.removeIf { it.id == example }
example3Object.setAll(it.map {FooModel})
}
I’m showing described model in listview and want to add objects of another kind(s) in the same list. I have a solution with sealed class, example of DifferentKindsOfInstances.kt:
sealed class DifferentKindsOfInstances{
data class Foo(val foo: FooModel): DiffrentKindsOfInstances()
data class Bar(val bar: BarModel): DiffrentKindsOfInstances()
}
let’s think BarModel is exact copy of FooModel, nevermind.
But if I wanna continue working with FooModel in a way I worked before(in MainControl) - how would the code look then?
it.foo.id doesn’t work for me
Here's a solution that references the sealed class members in two places: rendering the ListCell in cellFragment{} and in the binding of the selected sealed class item to the textfield string content.
class ItemModel1 ( val dataField1 : String )
class ItemModel2 ( val dataField2 : String )
sealed class ItemViewInstance {
data class Item1(val item1: ItemModel1): ItemViewInstance()
data class Item2(val item2: ItemModel2): ItemViewInstance()
}
class SealedClassDemoView : View("Sealed Class") {
val instances = listOf(
ItemViewInstance.Item1(ItemModel1("One")),
ItemViewInstance.Item2(ItemModel2("Two"))
).observable()
val selectedItemString = SimpleStringProperty()
override val root = vbox {
listview(instances) {
cellFormat {
when( it ) {
is ItemViewInstance.Item1 -> text = it.item1.dataField1
is ItemViewInstance.Item2 -> text = it.item2.dataField2
}
}
selectedItemString.bind(
Bindings.createStringBinding(
Callable {
val sel = selectionModel.selectedItemProperty().value
when (sel) {
is ItemViewInstance.Item1 -> sel.item1.dataField1
is ItemViewInstance.Item2 -> sel.item2.dataField2
else -> ""
}
},
selectionModel.selectedItemProperty()
)
)
}
textfield(selectedItemString)
padding = Insets(2.0)
spacing = 4.0
}
}
class SealedClassDemoApp : App(SealedClassDemoView::class)
fun main(args: Array<String>) {
launch<SealedClassDemoApp>(args)
}

How to get kotlin function's caller

With this example:
open class Parent {
fun some():Parent {
return this;
}
}
class A : Parent(){
val name:String? = null;
}
But then this code results in an error:
val a = A().some().some()
a.name // ERROR
EDITOR NOTE: based on comments of the author to answers below, the question is NOT about referencing a.name but really is about something like "how do I get the instance of the class or its name that first started the chain of method calls". Read all comments below until the OP edits this for clarity.
my final goal is to return caller's type and can call this caller's instance property, no more as , no more override, any idea?
Just like java, you can use stackTrace's getMethodName(). Refer to the kotlin doc.
Actially your example is working(if you add open keyword because all classes in Kotlin are final by default:
A.kt
open class A {
fun some(): A {
return this
}
}
B.kt
class B : A() {
val test = "test"
}
And usage
val tmpB = (B().some().some() as B)
val test = tmpB.test
Edited:
It because function some() return parent class which doesn't have child class property. So you need to cast it to child class.(Update code)
open class Parent{
open fun foo(): Parent {
return this;
}
}
This is your Parent class. Parent class has a method named foo(). foo() is a method of class A which will return the instance of it's own class. We must have to open the class and method because by default their visibility modifier is final.
class A : Parent() {
override fun foo(): A { return this }
}
This is a class named A which extends Parent class. foo() is a method of class A which will return the instance of it's own class.
We will call it like this:
var a = A().foo().foo()
Your class always return Parent instance. This class do not have any field with the name name. To do that you have 2 ways:
The first:
open class Parent{
fun some():Parent{
return this
}
}
class A :Parent(){
val name:String? = null
}
fun main() {
val a = (A().some().some() as A)
a.name = "";
}
The second:
open class Parent{
open fun some():Parent{
return this
}
}
class A :Parent(){
override fun some():A {
return this
}
val name:String? = null
}
fun main() {
val a = A().some().some()
a.name = "";
}
i have know how to do this:
#Avijit Karmakar
#Trần Đức Tâm
use inline function
inline fun <reified T:Any> some(sql: String):T {
return this as T ;
}