I haven't fully understood how SAM works. But woul...
# announcements
j
I haven't fully understood how SAM works. But would it be possible to mix it with enum classes? so instead of having something like this:
Copy code
fun interface Ordering {
    fun String.getOrdering(): List<String>
}

enum class CustomValueCriteriaOrder : Ordering {
    ALPHABETICALLY {
        override fun String.getOrdering(): List<String> {
            return emptyList()
        }
    }
}
I could have
Copy code
fun interface Ordering {
    fun String.getOrdering(): List<String>
}

enum class CustomValueCriteriaOrder : Ordering {
    ALPHABETICALLY { emptyList() }
}
d
Copy code
fun interface Ordering {
    fun String.getOrdering(): List<String>
}
enum class CustomValueCriteriaOrder(val ordering: Ordering) {
    ALPHABETICALLY { emptyList() }
}
Should do the trick.
Copy code
fun interface Ordering {
    fun String.getOrdering(): List<String>
}
enum class CustomValueCriteriaOrder(val ordering: Ordering): Ordering by ordering {
    ALPHABETICALLY { emptyList() }
}
If you really want the polymorphism.
j
Copy code
fun interface Ordering {
    fun String.getOrdering(): String
}
enum class CustomValueCriteriaOrder: Ordering {
    ALPHABETICALLY { override fun String.getOrdering() = "sorting rule" },
    OTHER_RULE { override fun String.getOrdering() = "sorting rule" }
}
enum class UserOrder: Ordering {
    NAME { override fun String.getOrdering() = "sorting rule" }
}

// Use cases
data class User1(val ordering: Ordering = CustomValueCriteriaOrder.ALPHABETICALLY)
data class User2(val ordering: Ordering = UserOrder.NAME)
This is basically what I want, but then I thought maybe SAM could improve on readability and allow me to remove the
override fun String.getOrdering()
part
d
I just noticed that it doesn't compile. This works.
Copy code
fun interface Ordering {
    fun String.getOrdering(): List<String>
}
enum class CustomValueCriteriaOrder(val ordering: Ordering): Ordering by ordering {
    ALPHABETICALLY({ emptyList() })
}
👍 1
Also, you don't seem to need an enum per se. So this could also work for you.
Copy code
fun interface Ordering {
	fun String.getOrdering(): List<String>
}
object CustomValueCriteriaOrder {
	val ALPHABETICALLY = Ordering { emptyList() }
}
j
Thanks, that seems to work perfectly 👍
The enum part is important for me. I'm exposing the enum over graphql, so a client can customize which ordering they want
a
Hm, may I ask a question, what is the use case for such SAM interface? You define a string extension that can only be used inside
Ordering
subclasses, you can’t use this extension if you have an instance of
Ordering
, can you?
j
I wrote string, but it will in my usecase be a QueryBuilder Object which then I can write custom logic for SQL query generation. The the client can get enum options of what sorting this data should be in. Perfect usecase for having a table view on frontend with pagination where you could press each column header to control the sorting
a
So for example you received
ALPHABETICALLY
ordering enum constant, this constant internally defines
QueryBuilder.getOrdering()
extension but you can’t use it from outside. So how do you plan to call
getOrdering()
then?
j
I have built a framework for that. I have a Criteria Interface which all of the different input types that are available for the client, for all types of data. This interface is extended per data type I have in the database, which for each of those ones I will write a custom enum which will use this SAM pattern. Which means I can have this
List<Ordering>
on my top level criteria interface. And have a single repository that does all SQL Queries and sortings by just calling this function with it's QueryBuilder.
Here's the end result in graphql 😛