2017-09-18 7 views
0

私は、SkillインターフェイスとSoundlessMovementインターフェイスを実装するクラスStealthを持っており、インターフェイスMasteryを実装しています。今度はSkillStealthに熟達度SoundlessMovementを追加し、SkillMasteryを確実にサポートします。ListのタイプをKotlinのインターフェースの実装に制限することはできますか?

は、私は、この(擬似Kotlin)のような何かをしたい:

interface Skill { 
    val masteries: List<Mastery<Skill>> // Mastery linked to type Skill 
} 

と実装と

interface Mastery<Skill> { // Every Mastery must be compatible with only one Skill 
    val masteryName: String 
} 

class Stealth : Skill { 
    override val masteries: ArrayList<Mastery<Stealth>() // Any Mastery bound to Stealth 
} 

class SoundlessMovement : Mastery<Stealth> { // Is a Mastery compatible with Stealth 
    override val masteryName = "Soundless Movement" 
} 

目的は、互換性のあるマスターのみをスキルに追加できるようにすることです。 このようなことも可能ですか?そしてもしそうなら、Kotlinでどのように実装することができますか?

+0

私は質問のタイトルが悪いと認識しています。私はちょうど問題をより良く記述する方法を知らない。 – zoku

+0

あなたのクラスデザインは理解できません。なぜMasteryがジェネリックパラメータを必要としますが、それを使用していないのですか?なぜスキルはそのクラスのリスト参照を保持していますか?あなたが達成したいこととあなたのクラス関係を説明できますか? – Joshua

+0

@Joshua構造は、コードの問題のある部分のみを表示するように単純化されています。簡単に言えば、別のインタフェースを実装しているファーストクラスにバインドされている別のクラスの型を持つリストを保持するインタフェースを実装するクラスを作成しようとします。目標は、それぞれの熟練を特定のスキルに結びつけることによって、スキルと熟練の混同を防ぐことです。 ペローコの答えはまさに私がやろうとしていたものです。 – zoku

答えて

3

私は本当にあなたを理解している場合、私は知らないが、私は、コードのこの部分はあなたの問題を解決思う:

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 
} 

ここで重要なのは、現在の実装をバインドするためにSkill<Self>を使用することです。また、class Stealth ...abstract class Stealth ...に変更したのは、がマスタタイプのと定義されているからです。別のオプションは、Kotlin's sealed class

を使用することができSelfが予約語でも同様のものではないことに注意してください。コードをちょうどTに変更すれば、このコードも機能します。私はSelfを使用して、あなたがそこに置くべきタイプを認識させるようにしました。

+0

ああ!それは理にかなっている。それは私がそれを聞いたことがない理由を説明します。それは 'Foo >'よりも読みやすくなります。今度は「自己」がキーワードではないことを知っているので、コードが何をしているのかも理解しています。それは私が思ったよりも簡単です。 – zoku

関連する問題