Javaでオブジェクト指向技術を使用するステートマシン用のフレームワークを作成しようとしています。 System
は、一度に1つだけ有効にすることができます。State
Java継承によるコード継承のコード再利用
public interface State {}
public interface System {
State currentState();
}
UpdateableSystem
と呼ばれるのは、私はその状態を確認し、変更するために、定期的に更新されるべきシステムの新しいタイプを追加したいとしましょう。それはタイプがUpdateableState
である州だけを持つことができます。
public interface UpdateableState extends State {
/**
* Check to see if the system should switch to a different state.
* @returns new state of the system
*/
UpdateableState update();
}
public interface UpdateableSystem extends System {
@Override
UpdateableState currentState();
/**
* Runs update method of the current state, or otherwise updates the system.
* @returns the current state of the system after the update
*/
UpdateableState update();
}
UpdateableSystem
のみのタイプUpdateableState
のある状態を持つことができ、かつUpdateableSystem
を使用して、クライアントがUpdateableState
のを期待していますので、私は、のみのみUpdateableState
、ないState
を返すようにcurrentState
メソッドをオーバーライド。
より多くのサブクラスが作成されるにつれて、多くのメソッドを何度もオーバーライドしないようにするには、ジェネリックが解決策のようです。 ここに更新されたインターフェイスがあります。
public interface System<SystemState extends State> {
SystemState currentState();
}
と
今public interface UpdateableState<SystemState extends UpdateableState<SystemState>> extends State {
SystemState update();
}
public interface UpdateableSystem<SystemState extends UpdateableState<SystemState>> extends System<SystemState> {
SystemState update();
}
は、システムや状態が注意する必要があることを、私は別のタイプ、インターフェースContext
を追加したいと言うことができます。 Context
はサブタイプすることができます。クライアントとContextState
サブタイプは、そのContext
サブタイプの完全なインターフェースを使用できる必要があります。
public interface Context {}
public interface ContextState<SystemContext extends Context, SystemState extends ContextState<SystemContext, SystemState>> extends UpdateableState<SystemState> {
SystemState updateWithContext(SystemContext context);
}
public interface ContextSystem<SystemContext extends Context, SystemState extends ContextState<SystemContext, SystemState>> extends UpdateableSystem<SystemState> {
// Some methods here that require SystemContext type
}
は突然、これらのパラメータ化された型は、混乱し、維持するのが困難であり、定型の全体トンになりました。
これは具体的な実装は、実施例のようになります。
class CarContext implements Context {...}
interface CarState extends ContextState<CarContext, CarState> {...}
class CarDrivingState implements CarState {}
class CarIdleState implements CarState {}
class Car implements ContextSystem<CarContext, CarState> {...}
ContextState
から継承されたメソッドのシグネチャがCarContext
によってパラメータ化されることになるので、各コンクリートCarState
が、CarContext
インタフェースによって提供される追加のメソッドにアクセスすることができるであろうタイプ。したがって、明示的なキャストはコンテキスト・パラメータupdateWithContext
には必要ありません。
最終的には、パラメータ化に追加の型を追加するときに問題があまりにも多いため、継承を使用してコードを再利用する設計の代替案がわかりません。また、可能な場合は明示的なキャストを避ける。このデザインを改善するための提案はありますか?
Javaジェネリックはテンプレートタイプではありません。このインタフェースのCarStateはContextState(例えば)を拡張し、 'インタフェースCarState extends ContextState 'と書くこともできます - 型のローカル名は単なる* label *です。 –
「ContextState」インターフェースの定義内でラベルとして機能しますが、 'CarState'インターフェースの定義内では、それらは実際のタイプでなければなりません。私の知る限り、実際のインターフェースやクラス。 – Ashes
もう一度お試しください。 Javaジェネリックは、コンパイル時型チェックシステムです。コンパイル後(実行時のオーバーヘッドはありません)、java.langには[** erased **](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html)されます。オブジェクト ';あなたが期待しているように見えるのは、それらがC++テンプレートのように動作することです。彼らはしない。 –