web-dev-qa-db-ja.com

列挙型で内部インターフェイスを実装する場合の循環継承

コンパイラエラーが発生する次の実装があります。

public enum FusionStat implements MonsterStatBuilderHelper {
    ATTACK {
        @Override
        public MonsterCard.MonsterCardBuilder safeCreateBuilder(final MonsterCard baseMonsterCard, final MonsterCard fusedMonsterCard, final FusionCard fusionCard) {
            Objects.requireNonNull(baseMonsterCard);
            Objects.requireNonNull(fusedMonsterCard);
            Objects.requireNonNull(fusionCard);
            if (baseMonsterCard.equals(fusedMonsterCard)) {
                throw new IllegalArgumentException("baseMonsterCard and fusedMonsterCard need to be different");
            }
            return new MonsterCard.MonsterCardBuilder(baseMonsterCard)
                    .attack(baseMonsterCard.getAttack() + (fusionCard.getFusionPower() * fusedMonsterCard.getAttack()));
        }
    },

    HITPOINTS {
        @Override
        public MonsterCard.MonsterCardBuilder safeCreateBuilder(final MonsterCard baseMonsterCard, final MonsterCard fusedMonsterCard, final FusionCard fusionCard) {
            Objects.requireNonNull(baseMonsterCard);
            Objects.requireNonNull(fusedMonsterCard);
            Objects.requireNonNull(fusionCard);
            if (baseMonsterCard.equals(fusedMonsterCard)) {
                throw new IllegalArgumentException("baseMonsterCard and fusedMonsterCard need to be different");
            }
            return new MonsterCard.MonsterCardBuilder(baseMonsterCard)
                    .maximumHitpoints((int)(baseMonsterCard.getMaximumHitpoints() + (fusionCard.getFusionPower() / 100d * fusedMonsterCard.getMaximumHitpoints())))
                    .hitpoints((int)(baseMonsterCard.getHitpoints() + (fusionCard.getFusionPower() / 100d * fusedMonsterCard.getHitpoints())));
        }
    };

    protected interface MonsterStatBuilderHelper extends MonsterStatBuilder {
        default MonsterCard.MonsterCardBuilder safeCreateBuilder(final MonsterCard baseMonsterCard, final MonsterCard fusedMonsterCard, final FusionCard fusionCard) {
            return createBuilder(baseMonsterCard, fusedMonsterCard, fusionCard);
        }
    }
}

@FunctionalInterface
interface MonsterStatBuilder {
    MonsterCard.MonsterCardBuilder createBuilder(final MonsterCard baseMonsterCard, final MonsterCard fusedMonsterCard, final FusionCard fusionCard);
}

最初の行involving FusionStatで循環継承エラーが発生します。

何が起こっているのか正確にはわかりません。私は最初に抽象クラスを実装し、enumがクラスを拡張できないことに気付くまで、enumにそれを拡張させたいと思っていました。次に、Java 8のデフォルトのメソッドを(ab)使用してみます。

私はコードがコンパイルされない理由についての思考プロセスに興味があり、safeCreateBuilder内の重複したコードをプルすることにより、コードの重複を削除しようとしました(まだそうする必要があります)。

55
skiwi

これは、そのクラスから継承しているクラス内で実装(継承)しているインターフェイスを実装(コーディング)しているためです。

私はその文章をもっと良くしたいのですが...

しかし、ここに視覚的な例があります。

Class A implements Interface B {

    Interface B {
    }
}

私の知る限り、これは許可されていません。クラスの外部でインターフェース(この場合はEnum)を定義する必要があります。

そのようです:

Interface B {
}

Class A implements Interface B {
}

ベストプラクティスは、おそらくそれらを異なるファイルに分割することです。

122
QuestionMarcs