I'm a beginner of Kotlin, I use Code A to define a complex class MDetail
, and use Code B to create a object aMDetail1
, it can work.
But the data construction is too bad to expand, if I include a new data class such as ScreenDef
in MDetail
just like Code C, all old code have to be rewriten.
Is there a good data construction for a complex class which include some classes ? I hope to the data construction can be expansion easily in future!
Code A
data class BluetoothDef(val Status:Boolean=false)
data class WiFiDef(val Name:String, val Status:Boolean=false)
data class MDetail (
val _id: Long,
val bluetooth: BluetoothDef,
val wiFi:WiFiDef
)
Code B
var mBluetoothDef1= BluetoothDef()
var mWiFiDef1= WiFiHelper(this).getWiFiDefFromSystem()
var aMDetail1= MDetail(7L,mBluetoothDef1,mWiFiDef1)
Code C
data class BluetoothDef(val Status:Boolean=false)
data class WiFiDef(val Name:String, val Status:Boolean=false)
data class ScreenDef(val Name:String, val size:Long)
...
data class MDetail (
val _id: Long,
val bluetooth: BluetoothDef,
val wiFi:WiFiDef
val aScreenDef:ScreenDef
...
)
The following code is based what s1m0nw1 said, I think it's easy to extend for future. Thanks!
Is there other more better way?
Version 1 Code
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
class MDetail(val _id: Long, val devices: MutableList<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
class UIMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
val btD = BluetoothDef(true)
val wfD = WiFiDef("MyWifi")
val xSc = ScreenDef("MyScreen", 1)
val m = MDetail(7L, mutableListOf(btD, wfD, xSc))
handleBluetoothDef(m.getDevice<BluetoothDef>())
handleWiFiDef(m.getDevice<WiFiDef>())
handleScreenDef(m.getDevice<ScreenDef>())
}
fun handleBluetoothDef(mBluetoothDef:BluetoothDef){ }
fun handleWiFiDef(mWiFiDef:WiFiDef){ }
fun handleScreenDef(mScreenDef:ScreenDef){ }
}
Version 2 Code (Expansion)
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
data class TimeLine(val Name: String): DeviceDef //Extend
class MDetail(val _id: Long, val devices: MutableList<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
class UIMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
val btD = BluetoothDef(true)
val wfD = WiFiDef("MyWifi")
val xSc = ScreenDef("MyScreen", 1)
val aTe = TimeLine("MyTimeline") //Extend
val m = MDetail(7L, mutableListOf(btD, wfD, xSc,aTe)) //Modified
handleBluetoothDef(m.getDevice<BluetoothDef>())
handleWiFiDef(m.getDevice<WiFiDef>())
handleScreenDef(m.getDevice<ScreenDef>())
handleTimeLine(m.getDevice<TimeLine>()) //Extend
}
fun handleBluetoothDef(mBluetoothDef:BluetoothDef){}
fun handleWiFiDef(mWiFiDef:WiFiDef){ }
fun handleScreenDef(mScreenDef:ScreenDef){ }
fun handleTimeLine(mTimeLine:TimeLine){} //Extend
Help
I have to replace interface with open class because I can't unserialize MDetail object from json string GSON.
but the fun inline fun <reified T> getDevice(): T{ }
can't return correct result, how can I modify? Thanks!
open class DeviceDef
data class BluetoothDef(val status:Boolean=false): DeviceDef()
data class WiFiDef(val name:String, val status:Boolean=false) : DeviceDef()
data class MDetail(val _id: Long, val deviceList: MutableList<DeviceDef>)
{
inline fun <reified T> getDevice(): T {
return deviceList.filterIsInstance(T::class.java).first()
}
}
I suggest to do the following: Your units (Wifi, Bluetooth etc.) should be abstracted by an interface (at least as a marker), which could be named DeviceDef
.
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
The MDetail
class can be instantiated with a variable list of these devices, so that no modifications are needed when new devices, such as ScreenDef
, are added:
class MDetail(val _id: Long, val devices: List<DeviceDef>)
Inside MDetail
, you can provide a method for filtering these devices:
class MDetail(val _id: Long, val devices: List<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
Now, it's pretty simple to work with the WifiDef
for example:
fun main(args: Array<String>) {
val btD = BluetoothDef()
val wfD = WiFiDef("")
val m = MDetail(7L, listOf(btD, wfD, ScreenDef("", 1)))
println(m.getDevice<WiFiDef>())
}
I hope this helps. If not, it might be necessary that you provide more details on how MDetail
is supposed to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With