当前位置: 首页 > 知识库问答 >
问题:

如何设计一个包含一些类的复杂类,以便将来在Kotlin中轻松地进行扩展?

微生德泽
2023-03-14

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

但是数据结构太糟糕,无法扩展,如果像代码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<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

帮助

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

但是有趣的是

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个答案

贺功
2023-03-14

每次将新属性添加到MDetail中时,请将新属性标记为null,并将默认值设置为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)
单于骁
2023-03-14

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

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

或者,如果您不希望ascreenedef为空,请为其添加一个默认值,如示例。通过这种方式,您可以保持现有的构造函数调用不变,并在需要时向构造函数调用添加新值此外,您还可以使用命名参数功能,在该功能中,您可以在调用构造函数时指定参数的名称。因此,如果要在不添加屏幕定义的情况下将GpsDef添加到MDetail,可以执行以下操作

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

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

法子昂
2023-03-14

我建议执行以下操作:您的单元(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应该如何工作的更多详细信息。

 类似资料:
  • 我需要包括一些必须在许多tmpls中重复的php代码。我怎么能做到这一点,可能是因为类包括?我怎么能写PHP文件与我的类在一个正确的方式?换句话说,我需要像 视图/类别/胎压监测/默认值。php 视图/文章/TPM/默认值。php 我的班级。php ... 更新:@Guilherme谢谢你!所以现在看起来 文件/mytemplate/html/com\u content/article/defau

  • 但任何时候我用这个: 我得到一个隐秘的错误: 我尝试使用自定义数据类型: 使用返回该类型的UDF: 但随后我得到另一个,它抱怨类型。 如何正确地编写可以返回复杂类型的UDF?

  • 问题内容: 我正在尝试为我们试图解决的遗传问题建模,并逐步加以解决。我可以从Spark示例成功运行PiAverage示例。该示例将一个圆圈“掷飞镖”(在本例中为10 ^ 6),并计算“落在圆圈中”的数量以估算PI 假设我要重复该过程1000次(并行),并对所有这些估计求平均值。我正在尝试寻找最好的方法,似乎会有两个调用要并行化?嵌套通话?有没有办法将地图链接或减少通话数量?我看不到 我想知道以下想

  • 生活中描述事物无非就是描述事物的 属性 和 行为。 如:人有身高,体重等属性,有说话,打架等行为。 事物名称(类名):人(Person) 属性:身高(height)、年龄(age) 行为(功能):跑(run)、打架(fight) Go 语言中用类来描述事物也是如此 属性:对应类中的成员变量。 行为:对应类中的成员方法。 定义类其实在定义类中的成员(成员变量和成员方法) 拥有相同或者类似 属性(

  • 问题内容: 如果我有几个具有所需功能的类,但想单独存储以进行组织,我可以扩展一个类以同时拥有这两个类吗? 即 编辑:我知道如何一次扩展一个类,但是我正在寻找一种使用多个基类立即扩展一个类的方法- AFAIK,您不能在PHP中做到这一点,但是应该有一些解决方法,而不必诉诸于, 问题答案: 回答您的编辑: 如果您确实想伪造多重继承,则可以使用魔术函数__call()。 尽管从A类用户的角度来看,这很丑

  • 所以我有一个多项目设置,看起来像这样