Reputation: 7236
I have a class Stealth
implementing the interface Skill
and a class SoundlessMovement
implementing the interface Mastery
. Now I want to add the mastery SoundlessMovement
to the Skill
Stealth
, while ensuring the Mastery
to be supported by the Skill
.
I want to do something like this (Pseudo-Kotlin):
interface Skill {
val masteries: List<Mastery<Skill>> // Mastery linked to type Skill
}
and
interface Mastery<Skill> { // Every Mastery must be compatible with only one Skill
val masteryName: String
}
with implementations:
class Stealth : Skill {
override val masteries: ArrayList<Mastery<Stealth>() // Any Mastery bound to Stealth
}
and
class SoundlessMovement : Mastery<Stealth> { // Is a Mastery compatible with Stealth
override val masteryName = "Soundless Movement"
}
The goal is to make sure that only compatible masteries can be added to a skill. Is something like this even possible? And if yes, how could it be implemented in Kotlin?
Upvotes: 0
Views: 144
Reputation: 7649
I don't know if I really understood you but I think this piece of code solves your problem:
interface Mastery<Skill> {
val masteryName: String
}
interface Skill<Self : Skill<Self>> { // forces every Skill to bound to itself
val masteries: List<Mastery<Self>>
}
abstract class Stealth : Skill<Stealth> {
override val masteries = ArrayList<Mastery<Stealth>>()
}
class SoundlessMovement : Mastery<Stealth> { // a Stealth mastery
override val masteryName = "Soundless Movement"
}
class SoundlessMovement2 : Mastery<Stealth> { // another Stealth mastery
override val masteryName = "Soundless Movement 2"
}
abstract class Archery : Skill<Archery> {
override val masteries = ArrayList<Mastery<Archery>>()
}
class SureShot : Mastery<Archery> { // some other mastery
override val masteryName = "Sure shot 2"
}
fun main(args: Array<String>) {
var list = ArrayList<Mastery<Stealth>>()
list.add(SoundlessMovement()) // compiles
list.add(SoundlessMovement2()) // compiles
list.add(SureShot()) // Doesn't compile
}
The key here is to use Skill<Self>
to bound the current implementations. Note also that I've changed class Stealth ...
to abstract class Stealth ...
since you're defining the mastery type. Another option could be using Kotlin's sealed class
Beware that Self
is not a reserved word nor anything similar. The code will also work if you just change it to just T
. I chose to use Self
just to make you aware what type you should put there
Upvotes: 3