##関数型インターフェース(functional interface)
関数型インターフェースとは, 抽象メソッドが一つだけ宣言されているインターフェースのこと.
それ以外に特に制約はない.
例えば, デフォルトメソッドやプライベートメソッドは複数持っていても問題ない.
##ラムダ式とは
クライアント(呼び出す側)でインターフェースの実装を与える機能のこと.
ラムダ式を使うことで, インターフェースを実装した具象クラスを作成する必要がなくなる.
ラムダ式は関数型インターフェースの実装を与える場合のみ可能.
なぜならば, 実装を与えたいインターフェースに複数の抽象メソッドがあった時, どの抽象メソッドに実装(定義)を与えるのかコンパイラが特定できない.
##クロージャ
メソッド内でラムダ式やローカルクラス, 匿名クラスを用いて実装を与えるとき, 実装を与えるブロック内でクライアントのローカル変数等を使用できる機能.
クロージャとして用いられた変数はラムダのインスタンスのフィールドとしてコピーされる(javaの場合).参照が渡される言語もある.
クロージャで渡された変数は不変である(final).
##コード例
public interface InfiniteIntSequence{
default public boolean hasNext(){ return true; }
public int next();
public static InfiniteIntSequence generate(IntSupplier s){
return s::getAsInt; //@1
}
public static InfiniteIntSequence iterate(int seed, IntUnaryOperator f){
return new InfiniteIntSequence(){
int lseed = seed; //@2
@Override public int next(){
int res=lseed;
lseed=f.applyAsInt(lseed);
return res;
}
};
}
public static InfiniteIntSequence random(int from, int until){
Random r = new Random();
int bound = until-from;
if(0<bound) return ()->r.nextInt(bound)+from;
else throw new IllegalArgumentException();
}
public static InfiniteIntSequence range(int from){
return iterate(from, i -> i+1 );
}
default public void forEach(IntConsumer c, int n){
while(n-- > 0 && hasNext() ) c.accept(next());
}
}
@1: return で返しているものは, InfiniteIntSequenceインターフェースを継承したclassのインスタンスで, next()メソッドをオーバーライドしている。InfiniteIntSequenceは関数型インターフェースなので, 抽象,ソッドは一つしかないことが担保されている。したがって, next()をオーバーライドすることをコンパイラが理解できるのでいろいろ書くことを省ける。
next()は引数なしでint型を返すシグネチャのメソッドである。