I have some default methods in an interface, like this:
/** Changes this component's color to the supplied [color] */
fun color(color: ChatColor?) = this.apply { component.color = color }
The problem is that, in subclasses, this method returns an instance of the interface so you can no longer chain anything that the interface doesn’t have!
I really want to do something like this for all those functions, and have Kotlin return this
automatically and recognize it as the proper type:
/** Changes this component's color to the supplied [color] */
chain fun color(color: ChatColor?) { component.color = color }
I’m aware of apply
, but look here. This is using the class my helper interface is meant to wrap:
Long code snippet
TextComponent(token.value).apply {
hoverEvent = HoverEvent(
HoverEvent.Action.SHOW_TEXT,
arrayOf(
TextComponent("This is a ").apply {
color = ChatColor.GOLD
addExtra(TextComponent("placeholder").apply { isBold = true })
addExtra(".\n")
},
TextComponent("Placeholders interact with ").apply {
color = ChatColor.GRAY
addExtra(TextComponent("PlaceholderAPI").apply { isBold = true })
addExtra(" in order to show dynamic text.\n")
},
TextComponent("If you don't have PlaceholderAPI, this won't work!").apply {
color = ChatColor.GRAY
}
)
)
}
As opposed to:
Another long code snippet
LTextComponent(token.value).hover(
HoverEvent(
HoverEvent.Action.SHOW_TEXT,
arrayOf(
!LTextComponent("This is a ")
.color(ChatColor.GOLD)
.extra(
LTextComponent("placeholder")
.bold(true)
)
.extra(LTextComponent(".\n")),
!LTextComponent("Placeholders interact with ")
.color(ChatColor.GRAY)
.extra(
LTextComponent("PlaceholderAPI")
.bold(true)
)
.extra(LTextComponent(".\n")),
!LTextComponent("If you don't have PlaceholderAPI, this won't work!")
.color(ChatColor.GRAY)
)
)
)
As is, that code works fine. However, I’d like to add an overload for extra(text: String)
in the LTextComponent
class, but not in the interface (which is value-agnostic). So I have this in the class:
/** Adds [extra] to this component as a child LTextComponent */
fun extra(text: String) = extra(LTextComponent(text))
But the problem is, all those chainable methods return the interface, so you have to call all the LTextComponent methods first, or cast, or something stupid like that!
Is there any way to create chainable methods like this without redefining them all manually in the conforming class? So, for example, a call to extra
or bold
return an instance of the class, rather than the interface it’s implementing.