総称型の変数に対して、extendsで限定してもインスタンスを代入できない
Javaの総称型について教えてください。
以下のようなコードを書きましたが、コンパイルエラーとなりました。
class Hoge {}
class Test<T> {
Test() {
// error: incompatible types: Hoge cannot be converted to T
T hoge = new Hoge();
}
}
そこで、総称型TをHogeという具体的なクラスに限定すればよいのでは、と考えて、以下のように修正しました。
class Test<T extends Hoge> {
しかし、同じコンパイルエラーが出てしまいます。
どのようにすれば実現できますでしょうか。(そもそも総称型にしている意味が無い、というご指摘はあるかと思いますが)
質問者追記:質問の発端となった具体的なコード
文章でうまく表現できている自信がありませんが、やりたいことは以下になります。
- 複数のアプリケーションに共通する処理は親クラスで共通部品として用意する
- それを継承する各アプリケーションは、ユーザAまたはユーザBというクラスを使う
- ユーザAとユーザBのどちらを使うのかは、アプリケーションによって事前に決まっている
- ユーザAとユーザBが持つメソッドは異なる
- ユーザのインスタンスは親クラスのメンバで持ちたい
- そのインスタンスを生成するのも、親クラスでやりたい(ここで躓いた)
具体的なコードは以下になります。
共通部品としてあらかじめ用意しておくクラス
// アプリケーションの流れを Template Method パターンで用意
abstract class AppBase<T extends UserBase> {
// ユーザの種類はサブクラスが決める
T user;
}
// ユーザの基底クラス
class UserBase {}
// ユーザA
class UserA extends UserBase {
// ユーザAは独自のメソッドmethodAを持っている
void methodA() {}
}
// ユーザB
class UserB extends UserBase {
// ユーザBは独自のメソッドmethodBを持っている
void methodB() {}
}
上記部品を使って実装するイメージ
// ユーザA向けのアプリケーションA
class AppForUserA extends AppBase<UserA> {
public AppForUserA() {
// ユーザAだけが持っている、user.methodA() を使った処理
}
}
// ユーザA向けのアプリケーションB
class AppForUserB extends AppBase<UserB> {
public AppForUserB() {
// ユーザBだけが持っている、user.methodB() を使った処理
}
}
ここで、AppBase
の user
メンバにユーザクラスのインスタンスを代入したいと思い、
abstract class AppBase<T extends UserBase> {
T user;
public AppBase() {
T user = new T();
// -> error: unexpected type
}
}
としようとしたところ無理であることを知り、そこで試しに、それ自体に意味はありませんが
abstract class AppBase<T extends UserBase> {
protected T user;
public AppBase() {
T user = new UserA();
// -> error: incompatible types: UserA cannot be converted to T
}
}
としてみてもエラーとなったため、質問した次第です。