Java / 基礎 / 制御構文 / for / 独自クラスを拡張forで使えるようにする

Java / 基礎 / 制御構文 / for / 独自クラスを拡張forで使えるようにする

ArrayList クラス等は拡張forに使えるので、じゃあ自分が独自に作ったクラスでそれをやりたい場合。

2段階。

  • そのクラスは拡張forで使えるか否かを教える
  • そのインスタンスから順番に取り出せるループ用の使い捨てインスタンスを作る

まずこのようなコレクションっぽいクラスを用意する。

public class Hoge{
    private String v1;
    private String v2;
    private String v3;
    private String v4;
    private String v5;
 
    public Hoge(String v1, String v2, String v3, String v4, String v5) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
        this.v4 = v4;
        this.v5 = v5;
    }
}

こいつを v1,v2…v5 と順番にやりたいなという話し。

当然だが、そもそも怒られて、↓のようには書けない。

Hoge hoge = new Hoge("a", "i", "u", "e", "o");
for(String s : hoge) {
    System.out.println(s);
}

まずこいつが拡張forで使えるよという印をつけます。よくある -able 系のインターフェースです。

メソッドを実装しろと怒られるので実装もします。

public class Hoge implements Iterable<String>{
    private String v1;
    private String v2;
    private String v3;
    private String v4;
    private String v5;
 
    public Hoge(String v1, String v2, String v3, String v4, String v5) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
        this.v4 = v4;
        this.v5 = v5;
    }
    @Override
    public Iterator<String> iterator() {
        return null;
    }
}

そうするととりあえず拡張forの構文で怒られなくなる。実行するとヌルポで落ちる。

ここで要素を順番に返すという Iterator という使い捨ての存在を作る。

特に拡張for以外では用途はほぼ無いので内部クラスとして作ってもよいだろう。

public class Hoge implements Iterable<String>{
    private String v1;
    private String v2;
    private String v3;
    private String v4;
    private String v5;
 
    public Hoge(String v1, String v2, String v3, String v4, String v5) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
        this.v4 = v4;
        this.v5 = v5;
    }
    @Override
    public Iterator<String> iterator() {
        HogeIterator it = new HogeIterator();
        it.setHoge(this);
        return it;
    }
 
    public static class HogeIterator implements  Iterator<String> {
        private String currentV;
        private Hoge hoge;
 
        public HogeIterator() {
            this.currentV = "v1";
        }
 
        public void setHoge(Hoge hoge) {
            this.hoge = hoge;
        }
 
        @Override
        public boolean hasNext() {
            return !this.currentV.equals("finished");
        }
 
        @Override
        public String next() {
            if(this.currentV.equals("v1")) {
                this.currentV = "v2";
                return this.hoge.v1;
            }
            if(this.currentV.equals("v2")) {
                this.currentV = "v3";
                return this.hoge.v2;
            }
            if(this.currentV.equals("v3")) {
                this.currentV = "v4";
                return this.hoge.v3;
            }
            if(this.currentV.equals("v4")) {
                this.currentV = "v5";
                return this.hoge.v4;
            }
            if(this.currentV.equals("v5")) {
                this.currentV = "finished";
                return this.hoge.v5;
            }
            throw new IndexOutOfBoundsException();
        }
    }
}   

このような感じの実装になる。実行すると a,i,u,e,o が出ることがわかると思う。

hasNext は次があるのか否かを返す。これを見て拡張forは next を呼び出すか否かの制御をする。 next で実際の値を取り出す。名前は next だが意味としては取り出したい今の値を返す。

java/basic/control_statements/for/my_foreach_class.txt · 最終更新: 2021-06-30 14:02 by ore