4

特定のサブクラスをパラメーターとして指定するインターフェースを実装するクラスが必要です。

public abstract Task implements TaskStatus<Task> {
  TaskStatus<T> listener;

  protected complete() {
      // ugly, unsafe cast
      callback.complete((T) this);
  }
}

public interface TaskStatus<T> {
   public void complete(T task);
}

しかし、単に task または の代わりに、使用される type-arg が、これを拡張する特定のクラスのものであることを保証したいと思います。

だから私が思いついた最高のものは次のとおりです。

public abstract Task<T extends Task> implements TaskStatus<T> {
}

次のように記述して拡張します。

public class MyTask extends Task<MyTask> {
}

しかし、これも有効です:

public class MyTask extends Task<SomeOtherTask> {
}

また、コールバックの呼び出しは ClassCastException で失敗します。それで、このアプローチは間違っていて壊れているのでしょうか、それとも私が見逃した正しい方法はありますか?

4

4 に答える 4

3

の中で何をしようとしているのかは明確ではありませんTask。ただし、ジェネリッククラスを次のように定義する場合Task<T>

class Task<T extends Task<T>> { ... }

次の2つが可能です。

class MyTask extends Task<MyTask> { ... }
class YourTask extends Task<MyTask> { ... }

ただし、次のことは禁止されています。

class MyTask extends Task<String> { ... }

上記の定義でTaskは、かなり高度な機能であるF有界量化を使用しています。詳細については、研究論文「オブジェクト指向プログラミングのF有界量化」を確認してください。

于 2008-09-30T18:30:45.267 に答える
1

適切に型付けされた this を返す getThis を追加することをお勧めします。確かにサブクラスが誤動作する可能性はありますが、それは常に真実です。回避するのは、キャストと ClassCastException の可能性です。

public abstract class Task<THIS extends Task<THIS>> {
    private TaskStatus<THIS> callback;

    public void setCallback(TaskStatus<THIS> callback) {
        this.callback = callback==null ? NullCallback.INSTANCE : callback;
    }

    protected void complete() {
        // ugly, unsafe cast
        callback.complete(getThis());
    }

    protected abstract THIS getThis();
}

public interface TaskStatus<T/* extends Task<T>*/> {
    void complete(T task);
}

public class MyTask extends Task<MyTask> {
    @Override protected MyTask getThis() {
        return this;
    }
}

この問題は、ビルダーでよく発生します。

于 2008-09-30T18:35:42.370 に答える
0

これを通じて何を達成しようとしているのか、少し理解できません。詳細を教えていただけますか?

コードを読んだところ、サブクラス化されるこれらのタスクがあり、タスクが完了すると、実行中のスレッドがタスクで complete() を呼び出すことがわかりました。この時点で、コールバックを呼び出してサブクラス オブジェクトに渡します。これが問題だと思います。潜在的なサブクラスの知識を抽象クラスに入れようとしていますが、これはノーノーです。

これはまた、この呼び出しを行うことができた場合、コールバックはスーパークラスとは異なるサブクラスで何をするのでしょうか?という疑問も生じます。

于 2008-09-30T18:35:29.407 に答える
0

コンストラクターでタイプargを強制する場合にのみ、これが機能していることを実際に確認できます。経由。introspection と Class.getSuperType() を使用して、型引数を検査し、型引数がこのクラスと一致することを確認できます。

次の行に沿ったもの:

assert getClass() == ((ParameterizedType) getSuperType()).getTypeArguments()[0];

(これは私の頭の上からのものです。JavaDocsをチェックして確認してください)。

コードのどこにコールバックが作成されているのかわかりません。上部の宣言を省略しました。

別のルートは、安全でないキャストを atm として削除することです。安全でないキャストが必要な理由を特定するための完全なフローがわかりません。

于 2008-09-30T18:36:55.440 に答える