1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

再帰的な型パラメータと自己型について

Posted at

はじめに

Effective Javaを読んでいて、出てきた「再帰的な型パラメータ」と「自己型」がわからなかったので、調べてまとめました。

再帰的な型パラメータとは?

再帰的な型パラメータとは、「型パラメータ自身を、制約(上限)として再び参照する」ような書き方です。
これにより、「TはT自身と比較可能な型でなければならない」などの制約を表現できます。

代表例:Comparable

Javaの標準ライブラリにある Comparable インタフェースがその代表です。

public interface Comparable<T> {
    int compareTo(T o);
}

多くのクラスでは、以下のように自分自身を型引数に指定して使います。

public class String implements Comparable<String> {
    public int compareTo(String o) {
        // String同士の比較
    }
}

より厳密な宣言

以下のように宣言すると、TはComparableを実装している型に限定されます:

public interface Comparable<T extends Comparable<T>> {
    int compareTo(T o);
}

これが「再帰的な型パラメータ」の形です。


なぜ再帰的な型パラメータが必要?

たとえば、コレクション内の最大値を求めるメソッド:

public static <T extends Comparable<T>> T max(Collection<T> c) { ... }

このように宣言することで、「TがT自身と比較できること」がコンパイル時に保証されます。

比較対象が不明確な例

以下のように Comparable<?> にしてしまうと:

public static <T extends Comparable<?>> T max(Collection<T> c) { ... }

比較対象が T である保証がなくなり、型安全ではなくなります

List<Comparable<Object>> list = ...;
max(list);  // コンパイルは通るが、比較の意味は曖昧

自己型(Self Type)とは?

本来の「自己型(Self Type)」とは、「このクラス自身の型」を意味する型システム上の概念です。
Scalaなどの言語ではサポートされていますが、Javaには明示的な自己型は存在しません。

Java における自己型の課題

Javaでメソッドチェーンを使って次のように書きたいとします:

new SubBuilder().foo().bar();

通常の書き方では、foo() の戻り値が BaseBuilder になってしまい、その後の bar() を呼べません。

例(うまくいかない)

class BaseBuilder {
    public BaseBuilder foo() {
        return this;
    }
}

class SubBuilder extends BaseBuilder {
    public SubBuilder bar() {
        return this;
    }
}

new SubBuilder().foo().bar();  // エラー

疑似自己型イデオムで解決!

Java では「再帰的な型パラメータ」を使って疑似的に自己型を実現できます。

基底クラスの工夫

class BaseBuilder<T extends BaseBuilder<T>> {
    public T foo() {
        return self();
    }

    protected T self() {
        return (T) this;
    }
}

サブクラスの実装

class SubBuilder extends BaseBuilder<SubBuilder> {
    public SubBuilder bar() {
        return this;
    }
}

これで、以下のようなコードが型安全に書けるようになります。

new SubBuilder().foo().bar();  // OK

疑似自己型イデオムの構成

要素 内容
<T extends BaseBuilder<T>> 再帰的な型パラメータで自己型を表現
foo() の戻り値を T サブクラスで型が適切に適用される
self() メソッドで型キャストを統一 安全で柔軟なキャスト処理

⚠ 注意点

  • self() 内のキャストは安全設計が前提(設計ミスがあると ClassCastException になる)
  • ジェネリクスの構文が複雑になり、理解が難しくなることも

まとめ

項目 ポイント
再帰的な型パラメータ 型の安全性・表現力を高めるための仕組み
Comparable<T extends Comparable> 比較可能性を型レベルで制約できる
Javaに自己型はない その代替手段として疑似自己型イデオムが使われる
メソッドチェーンとの相性が良い ビルダーパターンなどで型安全な設計が可能

おわりに

引き続き、Effective Javaの勉強をしていきたいです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?