Search code examples
androidkotlinandroid-fragments

How to use one specific function in multiple classes without actually copying its code in all the classes in Kotlin?


I have a function named withColor() that is required to be called in class A and class B 's Snackbar class . I don't want to copy paste its code in each of this classes again and again.

fun Snackbar.withColor(@ColorInt colorInt:Int): Snackbar { this.view.setBackgroundColor(colorInt) return this }

This function is called in Snackbar usage of Class A and class B like this

class A bindinpercentproblemsFragment.radioGroup10Percentage?.setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener{ group, checkedId ->

        val isChecked = bindinpercentproblemsFragment.radioButton37Percentage.isChecked
        if (isChecked) {
            Snackbar.make(requireView(), "Correct", Snackbar.LENGTH_LONG)
                .withColor(Color.rgb(0, 128, 0))
                .show()

        } else {
            Snackbar.make(requireView(), "InCorrect", Snackbar.LENGTH_LONG)
                .withColor(Color.rgb(255, 0, 0))
                .show()
        }

    })

class B

  binding.radioGroup10HCF?.setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener{ group, checkedId ->

        val isChecked = binding.radioButton40HCF.isChecked
        if (isChecked) {
            Snackbar.make(requireView(), "Correct", Snackbar.LENGTH_LONG)
                .withColor(Color.rgb(0, 128, 0))
                .show()

        } else {
            Snackbar.make(requireView(), "InCorrect", Snackbar.LENGTH_LONG)
                .withColor(Color.rgb(255, 0, 0))
                .show()
        }

    })

Solution

  • If this function operates on A and B's instance state, then you should probably move that common state into a parent (abstract) class, define that method in the parent class, and make A and B inherit from that parent class:

    abstract class Parent {
        protected var commonState: Int = 42
        
        fun sharedMethodAffectingState() {
            commonState++
        }
    }
    
    class A : Parent() {
        fun doSomethingA() {
            sharedMethodAffectingState()
        }
    }
    
    class B : Parent() {
        fun doSomethingB() {
            sharedMethodAffectingState()
        }
    }
    

    If this function is stateless, then you still have multiple options.

    If it is really semantically linked to A, and incidentally used in B, you may want to put it in A's companion object:

    class A {
        companion object {
            fun someFunctionThatMakesSenseInNamespaceA()
        }
    }
    
    class B {
        fun doSomething() {
            A.someFunctionThatMakesSenseInNamespaceA()
        }
    }
    

    If the function is stateless and doesn't have a more obvious relation to A than to B, then it should probably live outside of both these classes. It could be a top-level function, a top-level extension function, or part of an object that serves as a namespace. But the choice here depends on what the function does and what makes the most sense semantically:

    // pollutes the global namespace, use with care, and watch out for the visibility
    fun topLevel() { ... }
    
    // OK if it acts on SomeType and makes sense to exist on this type
    // in the scope defined by the visibility of the function. If public,
    // make sure the function makes sense for everyone using SomeType.
    fun SomeType.topLevelExtension() { ... }
    
    // Generally safe, but not very idiomatic in some situations
    object SomeNamespace {
    
        fun sharedFunctionAccessibleGlobally() { ... }
    }