Интерфейсы не имеют полей, 'field' IInstructions.OpCode
является константой (неявным public static final
), и хотя LDAInstruction.OpCode
является полем, которое не имеет значения в данном коде.С IInstrunctions instructions
выражение instructions.OpCode
относится к константе (имейте в виду, что ссылаться на статические элементы таким способом считается плохой практикой, и большинство IDE и статических анализаторов будут предупреждать вас об этом).
Это также объясняет значение, показанное IntelliJ: в цикле код ссылается на IInstructions.OpCode
, поэтому он показывает значение 0
, при проверке фактического объекта он знает, что это экземпляр LDAInstruction
, который содержитполе opCode
со значением 58
.
Визуализация кода IntelliJ также дает подсказку об этом: фиолетовый курсивный рендеринг является статическим полем, а фиолетовый «нормальный» (не курсив)) рендеринг - это поле экземпляра.
Вы должны удалить OpCode
из интерфейса и вместо этого объявить получатель (byte getOpCode()
, затем подклассы должны реализовать этот получатель, чтобы вернуть правокод для этой инструкции.
Я также предлагаю вам ознакомиться с соглашениями об именах Java: константа будет полностью прописной (например, OP_CODE
), а поля начинаютсяс буквой в нижнем регистре (например, opCode
), поля обычно , а не public
, и в этом случае это, вероятно, должно быть окончательное поле, поэтому его нельзя (случайно или намеренно) изменить.
Вам также следует рассмотреть возможность реализации этого как перечисления, так как технически вам нужен только один экземпляр инструкции, например
public enum Instruction {
LDA(Byte.valueOf("00111010",2)) {
@Override
public void execute(MachineState machineState) {
// your implementation.
}
},
// other instructions
;
private final byte opCode;
Instruction(byte opCode) {
this.opCode = opcode;
}
public abstract void execute(MachineState machineState);
public final byte getOpCode() {
return opCode;
}
}
В этом случае вы можете использовать метод enum name()
вместо определения отдельного мнемонического поля + геттер.И вы можете использовать статический метод enum valueOf(String)
для получения экземпляров по имени.
Но в зависимости от размера реализаций execute и количества инструкций это может быть не лучшим решением.
Другой подход - использовать абстрактный класс вместо (или в дополнение к) интерфейса, например:
public abstract class AbstractInstruction {
private final byte opCode;
private final String mnemonic;
protected AbstractInstruction(byte opCode, String mnemonic) {
this.opCode = opCode;
this.mnemonic = mnemonic;
}
public abstract execute(MachineState machineState);
public final byte getOpCode() {
return opCode;
}
public final String getMnemonic() {
return mnemonic;
}
}