Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

143
Views
Custom comparison for the enum class

I have a data class TestDataClass that has a custom equals() method, in order to consider the given threshold while comparing the Price property that looks like:

    private val THRESHOLD: Double = 1e-7
    
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as TestDataClass

        if (id != other.id) return false
        if (kotlin.math.abs(price - other.price) > THRESHOLD) return false
        if (curr != other.curr) return false
        if (desc != other.desc) return false
        if (quantity != other.quantity) return false

        return true
      }

Then there is an enum class that builds its properties based on the objects of the TestDataClass as:

enum class TestDataClassColumns(private val expr: (TestDataClass) -> Any) {
  Price({ it.price }),
  Curr({ it.curr }),
  Description({ it.desc }),
  Quantity({ it.quantity });
}

Furthermore, I have a checkData() method in the enum class TestDataClassColumns that acts is used for the comparison and returns the properties that were not equal:

fun checkData(obj1: TestDataClass?, obj2: TestDataClass?): Boolean = expr(obj1) != expr(obj2)

Null check is there, just removed it from post to have more visibility.

So far, the equals() of TestDataClass works correct, however I have no idea, how to incorporate the THRESHOLD into the checkData() of enum class TestDataClassColumns(). Any ideas how to do it? The overall design should remain the same, meaning that the classes should be there. Here is the link to playground with some examples - Kotlin Playground

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

In order to access the THRESHOLD from TestDataClassColumns, you have to move it to the companion object of your TestDataClass and make it public.

Then you can alter your TestDataClassColumns as follows:

enum class TestDataClassColumns(
    private val expr: (TestDataClass) -> Any, 
    private val uneq: (TestDataClass, TestDataClass) -> Boolean = { x,y -> x != y }
) {
  Price({ it.price }, { x, y -> kotlin.math.abs(x.price - y.price) > TestDataClass.THRESHOLD }),
  Curr({ it.curr }),
  Description({ it.desc }),
  Quantity({ it.quantity });

  fun checkData(obj1: TestDataClass?, obj2: TestDataClass?): Boolean = if (obj1 == null || obj2 == null) true else uneq(expr(obj1), expr(obj2))
}
over 4 years ago · Santiago Trujillo Report

0

checkData isn't comparing TestDataClasses directly, it's just running some function on each that returns an Any, and comparing those Anys - how would you apply a Double threshold there?

Seems like what you want is to take two TestDataClass instances and get them to compare themselves by one of their properties. That way they can handle each property appropriately, and if there is a threshold to consider it's an internal detail.

Probably the easiest way is to just create a price comparison function in your class, and make the equals function refer to it:

fun isSamePrice(other: TestDataClass) = kotlin.math.abs(price - other.price) <= THRESHOLD

override fun equals(other: Any?): Boolean {
    ...
    if (!isSamePrice(other)) return false
    ...
}

Then you can make your enum call that - instead of having a function that spits out values, which you then compare, you can have a function that uses two TestDataClass instances instead:

enum class TestDataClassColumns(private val compare: TestDataClass.(TestDataClass) -> Boolean) {
  Price({ isSamePrice(it) }),
  Curr({ curr == it.curr }),
  Description({ desc == it.desc }),
  Quantity({ quantity == it.quantity });

  fun checkData(obj1: TestDataClass?, obj2: TestDataClass?): Boolean =
    if (obj1 == null || obj2 == null) true else !obj1.compare(obj2)
}

All you need to do is initialise with a function that calls that comparison function on the class, and it's all handled internally - if the TestDataClass considers the prices equal, they are! And because it's internal, its equals function can call the same logic, which is important - keeps things consistent and all in the right place.


The downside is that all the others need a function that explicitly compares properties, which is nice and simple but there's the possibility someone won't wire up the correct property on one to the same on the other. You could create a comparison function for each property (isSameQuantity etc) so that how the comparison is made is always an internal detail, instead of making the enum decide for some of them.

You can also write the function call as a reference like this if you like:

enum class TestDataClassColumns(private val compare: TestDataClass.(TestDataClass) -> Boolean) {
  Price(TestDataClass::isSamePrice),

I used a lambda for consistency with the others, but if you did end up making a function for each, that might be neater!


Another option would be doing it your way, but instead of price being a Double, it's a custom type with its own equals function. That way you could init it with a double value, but when you compare it with another MyPrice by equality, it internally uses a threshold value. Basically you're getting around the fact that comparing Doubles just does straight equality, using your own type lets you tweak that behaviour. But obviously everything else has to handle the fact it's not a Double, and that value needs to be accessed through a property, etc

over 4 years ago · Santiago Trujillo Report

0

I would suggest to create a wrapper for a Double and use that in the enum. Something like

class MyDouble(val double: Double) {
    private val THRESHOLD: Double = 1e-7
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as MyDouble

        if (kotlin.math.abs(double - other.double) > THRESHOLD) return false
        return true
    }
}

And then the enum will be like

enum class TestDataClassColumns(private val expr: (TestDataClass) -> Any) {
    Price({ MyDouble(it.price) }),
    Curr({ it.curr }),
    Description({ it.desc }),
    Quantity({ it.quantity });

    fun checkData(obj1: TestDataClass?, obj2: TestDataClass?): Boolean = if (obj1 == null || obj2 == null) true else expr(obj1) != expr(obj2)
}

TestDataClass can stay the same that way. This will work for your example. But I don't know if it will break other parts of your code

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!