関数オブジェクトのアシストコンストラクタ

1366 ワード

1つのクラスに複数のコンストラクタが必要になる場合があります.Scalaの主コンストラクタ以外のコンストラクタを補助コンストラクタと呼ぶ.たとえば分母が1の有理数は分子だけを書くともっと簡潔です.そのため、Rational(5,1)をRational(5)と略したほうがいいかもしれません.これに対してRationalには分子のみを取り込むアシストコンストラクタを追加し,分母を1に設定しておく必要がある.例:
package scalaTest
class Rational(n:Int,d:Int) {
    require(d != 0)
    val number:Int = n
    val denom:Int = d
    def this(n:Int) = this(n,1)    //     
    override def toString = number + "/" + denom
    def add(that:Rational):Rational = {
        new Rational(number * that.denom + that.number * d , d * that.denom)
    }
    def lessThan(that:Rational) = {
        this.number * that.denom < that.number * this.denom
    }
    def max(that:Rational) = {
        if(this.lessThan(that)) that else this
    }
}

Scalaのアシストコンストラクタ定義はdef this(...)から始まる.関数本体はほぼ完全にホストコンストラクタの呼び出しであり,パラメータnを分子とし,1を分母として伝達した.Scalaの各補助コンストラクタの最初の動作は,同類の他のコンストラクタを呼び出すことである.すなわちscalaクラスの各アシストコンストラクタは「this(......)」形式で始まる.呼び出されたコンストラクタは、プライマリコンストラクタであってもよいし、他の定義されたアシストコンストラクタであってもよい.ルールの根本的な結果は、各scalaのコンストラクタ呼び出しが最終的にプライマリコンストラクタの呼び出しに終わるため、プライマリコンストラクタはクラスの唯一のエントリポイントである.
Javaに詳しい場合は、なぜscalaコンストラクタのルールがjavaよりも厳しいのか不思議に思うかもしれません.Javaのコンストラクタの最初の動作は2つの選択しかありません.同類の他のコンストラクタを呼び出すか、スーパークラスのコンストラクタを直接呼び出すかです.Scalaクラスには、スーパークラスのコンストラクタを呼び出すことができるのはプライマリコンストラクタのみです.Scalaのこのような厳しい制限は、実際にはscalaのコンストラクタをjavaコンストラクタに比べてより明確で簡潔にするための代価である.