Kotlin将来如何设计一个复杂的课程来增加课程的扩展性?

我是Kotlin的初学者,我使用代码A来定义一个复杂的类MDetail ,并使用代码B创建一个对象aMDetail1 ,它可以工作。

但是数据结构太难扩展了,如果像Code C那样在MDetail包含ScreenDef这样的新数据类,那么所有的旧代码都必须重写。

对于包含一些类的复杂类是否有很好的数据结构? 我希望今后的数据建设可以轻松扩展!

代码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 ) 

代码B

 var mBluetoothDef1= BluetoothDef() var mWiFiDef1= WiFiHelper(this).getWiFiDefFromSystem() var aMDetail1= MDetail(7L,mBluetoothDef1,mWiFiDef1) 

代码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 ... ) 

下面的代码是基于s1m0nw1说的,我想以后很容易扩展。 谢谢!

还有其他更好的方法吗?

版本1代码

 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) { inline fun  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()) handleWiFiDef(m.getDevice()) handleScreenDef(m.getDevice()) } fun handleBluetoothDef(mBluetoothDef:BluetoothDef){ } fun handleWiFiDef(mWiFiDef:WiFiDef){ } fun handleScreenDef(mScreenDef:ScreenDef){ } } 

版本2代码(扩展)

 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) { inline fun  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()) handleWiFiDef(m.getDevice()) handleScreenDef(m.getDevice()) handleTimeLine(m.getDevice()) //Extend } fun handleBluetoothDef(mBluetoothDef:BluetoothDef){} fun handleWiFiDef(mWiFiDef:WiFiDef){ } fun handleScreenDef(mScreenDef:ScreenDef){ } fun handleTimeLine(mTimeLine:TimeLine){} //Extend 

帮帮我

我必须更换接口与公开类,因为我不能从json字符串GSON反序列化MDetail对象。

但好玩的inline fun getDevice(): T{ }不能返回正确的结果,我该如何修改? 谢谢!

 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) { inline fun  getDevice(): T { return deviceList.filterIsInstance(T::class.java).first() } } 

我建议做以下事情:你的单位(Wifi,蓝牙等)应该被一个接口(至少作为一个标记)抽象,可以被命名为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 

MDetail类可以通过这些设备的variables列表进行实例化,以便在添加新设备(如ScreenDef时不需要进行任何修改:

 class MDetail(val _id: Long, val devices: List) 

MDetail里面,你可以提供一个过滤这些设备的方法:

 class MDetail(val _id: Long, val devices: List) { inline fun  getDevice(): T { return devices.filterIsInstance(T::class.java).first() } } 

现在,使用WifiDef的例子非常简单:

 fun main(args: Array) { val btD = BluetoothDef() val wfD = WiFiDef("") val m = MDetail(7L, listOf(btD, wfD, ScreenDef("", 1))) println(m.getDevice()) } 

我希望这有帮助。 如果没有,可能需要提供关于MDetail应该如何工作的更多细节。

我不是一个Kotlin专家,但我会建议在MDetail的构造函数中添加默认值

 data class MDetail ( val _id: Long, val bluetooth: BluetoothDef, val wiFi:WiFiDef val aScreenDef:ScreenDef? = null, val aGpsDef: GpsDef = GpsDef() ... ) 

或者如果您不希望aScreenDef为空,请为其添加默认值,如aGpsDef示例。 这样,您可以保持已有的构造函数调用不变,并在需要时向构造函数调用添加新的值。

另外,还可以使用命名参数function,您可以在调用构造函数时指定参数的名称。 所以如果你想添加GpsDefMDetail而不添加ScreenDef你可以做以下的事情

 val detail = MDetail(id, bluetooth, wifi, aGpsDef = GpsDef()) 

请注意,如果您使用的是Java构造函数,则可能需要为构造函数使用@JvmOverloads批注,该批注@JvmOverloads编译器根据具有默认值的可选参数生成多个构造函数。

每次在MDetail添加一个新的属性,标记新的属性为空,并将默认值设置为null。 喜欢这个

 data class MDetail ( val _id: Long, val bluetooth: BluetoothDef, val wiFi: WiFiDef, val screen: ScreenDef? = null, ... ) 

不要忘记创建一个新的实例时,提供具体的属性名称,像这样

 var aMDetail1= MDetail(7L, mBluetoothDef1, mWiFiDef1, screen = mScreenDef1)