Home > Software design >  How to access implement member property in kotlin
How to access implement member property in kotlin

Time:02-19

Hey I am working in kotlin. I create a tree data structure. I create open class called VariantNode and implement in three child class QuantityNode, StrengthNode, SubscriptionNode.

VariantNode.kt

open class VariantNode {
    var value: ProductValue? = null
    var children: MutableList<VariantNode> = arrayListOf()
}

QuantityNode.kt

class QuantityNode : VariantNode() {
    var defaultValue: Boolean? = null
}

StrengthNode.kt

class StrengthNode : VariantNode() {
    var pricePerUnit: String? = null
    var defaultValue: Boolean? = null
}

SubscriptionNode.kt

class SubscriptionNode : VariantNode() {
    var defaultValue: Boolean? = null
}

I want to access defaultValue and set value, but I am getting error Unresolved reference: defaultValue

ActivityViewModel.kt

class ActivityViewModel : ViewModel() {

    var baseNode: VariantNode = VariantNode()
    private val defaultValueId = "12643423243324"

    init {
        createGraph()
    }

    private fun createGraph() {
        val tempHashMap: MutableMap<String, VariantNode> = mutableMapOf()
        val getUnSortedDataList = getUnSortedDataList()
        val sortedList = getUnSortedDataList.sortedWith(
            compareBy<ProductVariant> {   // or compareByDescending
                it.strength?.value?.toInt() ?: 0   // or java.lang.Integer.MAX_VALUE
            }.thenBy {                    // or thenByDescending
                it.quantity?.value?.toInt() ?: 0   // or java.lang.Integer.MAX_VALUE
            }
        )

        sortedList.forEach { productVariant ->
            productVariant.strength?.let { strength ->
                baseNode.defaultValue = productVariant.id == defaultValueId // getting error in here

                if (tempHashMap.containsKey("strength_${strength.value}")) {
                    return@let
                }
                val tempNode = StrengthNode().apply {
                    value = strength
                    pricePerUnit = productVariant.pricePerUnit?.value
                }
                baseNode.children.add(tempNode)
                tempHashMap["strength_${strength.value}"] = tempNode
            }
            productVariant.quantity?.let { quantity ->
                if (tempHashMap.containsKey("strength_${productVariant.strength?.value}_quantity_${quantity.value}")) {
                    return@let
                }
                val tempNode = QuantityNode().apply {
                    value = quantity
                }
                val parent =
                    tempHashMap["strength_${productVariant.strength?.value}"] ?: baseNode
                parent.children.add(tempNode)

                tempHashMap["strength_${productVariant.strength?.value}_quantity_${quantity.value}"] =
                    tempNode
            }
            productVariant.subscription?.let { subscription ->
                val tempNode = SubscriptionNode().apply {
                    value = subscription
                }
                val parent =
                    tempHashMap["strength_${productVariant.strength?.value}_quantity_${productVariant.quantity?.value}"]
                        ?: baseNode
                parent.children.add(tempNode)
            }
        }
    }

}

enter image description here

My idea to update the defaultValue because I have defaultValueId and want to match with this defaultValue and set in each variant node type. Any suggestion how to do in better way would be great. My ActivityViewModel link

UPDATE after @snachmsm suggestion, I used first approach

private fun createGraph() {
        val tempHashMap: MutableMap<String, VariantNode> = mutableMapOf()
        val getUnSortedDataList = getUnSortedDataList()
        val sortedList = getUnSortedDataList.sortedWith(
            compareBy<ProductVariant> {   // or compareByDescending
                it.strength?.value?.toInt() ?: 0   // or java.lang.Integer.MAX_VALUE
            }.thenBy {                    // or thenByDescending
                it.quantity?.value?.toInt() ?: 0   // or java.lang.Integer.MAX_VALUE
            }
        )

        sortedList.forEach { productVariant ->
            productVariant.strength?.let { strength ->
                baseNode.defaultValue = productVariant.id == defaultValueId
                if (tempHashMap.containsKey("strength_${strength.value}")) {
                    return@let
                }
                val tempNode = StrengthNode().apply {
                    value = strength
                    pricePerUnit = productVariant.pricePerUnit?.value
                }
                baseNode.children.add(tempNode)
                tempHashMap["strength_${strength.value}"] = tempNode
            }
            productVariant.quantity?.let { quantity ->
                baseNode.defaultValue = productVariant.id == defaultValueId
                if (tempHashMap.containsKey("strength_${productVariant.strength?.value}_quantity_${quantity.value}")) {
                    return@let
                }
                val tempNode = QuantityNode().apply {
                    value = quantity
                }
                val parent =
                    tempHashMap["strength_${productVariant.strength?.value}"] ?: baseNode
                parent.children.add(tempNode)

                tempHashMap["strength_${productVariant.strength?.value}_quantity_${quantity.value}"] =
                    tempNode
            }
            productVariant.subscription?.let { subscription ->
                baseNode.defaultValue = productVariant.id == defaultValueId
                val tempNode = SubscriptionNode().apply {
                    value = subscription
                }
                val parent =
                    tempHashMap["strength_${productVariant.strength?.value}_quantity_${productVariant.quantity?.value}"]
                        ?: baseNode
                parent.children.add(tempNode)
            }
        }
    }

CodePudding user response:

baseNode is an VariantNode instance (as sortedList holds this type of objects) , which doesn't have own defaultValue, thus you can't access it. as all your extending classes contains it - this variable should be placed in VariantNode instead of each extender separately (duplicated code in fact), thats the purpose of object extending

open class VariantNode {
    var value: ProductValue? = null
    var children: MutableList<VariantNode> = arrayListOf()
    var defaultValue: Boolean? = null
}

and remove defaultValue from all other extending classes

another way is to check instance type of baseNode, but in your case this isn't proper approach

if(baseNode is QuantityNode) {
     (baseNode as QuantityNode).defaultValue = ...
}
else if(baseNode is SubscriptionNode) ...

first approach will reduce your whole code-base with two lines (3 removed, 1 added), second one will add whole cascade of ifs, which will be copied into other places in code, in which you will iterate through List. and when you add new extender of VariantNode - you will have to inspect whole code base, looking for such if cascade and adding yet another else if. with first approach new VariantNode extender will inherit defaultValue automatically

  • Related