如何设计一个复杂的课程,在Kotlin将来可以轻松扩展一些课程?

时间:2017-12-01 03:28:34

标签: java kotlin

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

但数据构建太糟糕了,如果我在ScreenDef中包含MDetail等新数据类,就像代码C一样,所有旧代码都必须重写。

对于包含某些类的复杂类,是否有良好的数据结构?我希望将来可以轻松扩展数据构建!

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

版本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<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

帮助

我必须用open类替换接口,因为我无法从json字符串GSON中反序列化MDetail对象。

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

3 个答案:

答案 0 :(得分:4)

我建议您执行以下操作:您的单位(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类,以便在添加新设备(例如ScreenDef)时不需要进行任何修改:

class MDetail(val _id: Long, val devices: List<DeviceDef>)

MDetail内,您可以提供过滤这些设备的方法:

class MDetail(val _id: Long, val devices: List<DeviceDef>) {

    inline fun <reified T> getDevice(): T {
        return devices.filterIsInstance(T::class.java).first()
    }
}

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

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

我希望这会有所帮助。如果没有,则可能需要提供有关MDetail应如何工作的更多详细信息。

答案 1 :(得分:3)

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

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

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

另外,您还可以使用named arguments功能调用构造函数时指定参数的名称。因此,如果您想在不添加GpsDef的情况下将MDetail添加到ScreenDef,则可以执行以下操作

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

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

答案 2 :(得分:-1)

每次向$mysqli->query(' CREATE TABLE `crm`.`roles` ( `id` TINYINT(1) NOT NULL AUTO_INCREMENT, `role_name` VARCHAR(20) NOT NULL, `edit` TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (`id`) );') or die($mysqli->error); $mysqli->query(' CREATE TABLE `crm`.`accounts` ( `id` INT NOT NULL AUTO_INCREMENT, `role` TINYINT(1) NOT NULL DEFAULT 1, `user_name` VARCHAR(20) NOT NULL, `password` VARCHAR(100) NOT NULL, `email` VARCHAR(100) NOT NULL, `first_name` VARCHAR(50) NOT NULL, `last_name` VARCHAR(50) NOT NULL, `hash` VARCHAR(32) NOT NULL, `active` BOOL NOT NULL DEFAULT 0, PRIMARY KEY (`id`), FOREIGN KEY (`role`) REFERENCES roles(`id`) );') or die($mysqli->error); 添加新属性时,请将新属性标记为可空,并将默认值设置为null。像这样

MDetail
在创建新实例时不要忘记,提供特定的属性名称,例如

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