読者です 読者をやめる 読者になる 読者になる

夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

駄目ネタで試すScala 引数 〜魔法少女まどか☆マギカ編〜

てなわけで(?) ネタ編第2回です。
適切なネタがパッと他に思い浮かばなかったので今回も魔法少女まどか☆マギカ継続で。
今度は何をネタにするかなぁ。。。。

オブジェクト指向言語に限らず、
クラスやメソッドで、
『いくつかの引数は省略しても動くようにしたい』ということはよくあると思います。

その時、Javaだと下記のように同名メソッドオーバーロードして
同名メソッドをいくつも記述することになります。

■PuellaMagi.scala(変更前)

package jp.gr.kmtn.scalatutorial.defaultvalue

/**
 * 「魔法少女」クラス
 *
 * @author Fukushi-
 */
class PuellaMagi() {

  /**
   * 名前を示すフィールド
   */
  var name_ = "";

  /**
   * 保持する武器を示すフィールド
   */
  var weapon_ = "";

  /**
   * 固有魔法を示すフィールド
   */
  var magica_ = "";

  /**
   * 契約を行い、魂をソウルジェムに移して肉体をハードウェアに変換する。
   *
   * @param name 名前
   */
  def sealToSoulJem(name: String) =
    {
      this.name_ = name;
      this.weapon_ = "魔法のステッキ";
      this.magica_ = "光の魔法";
    }

  /**
   * 契約を行い、魂をソウルジェムに移して肉体をハードウェアに変換する。
   *
   * @param name 名前
   * @param weapon 保持する武器
   */
  def sealToSoulJem(name: String, weapon: String) =
    {
      this.name_ = name;
      this.weapon_ = weapon;
      this.magica_ = "光の魔法";
    }

  /**
   * 契約を行い、魂をソウルジェムに移して肉体をハードウェアに変換する。
   *
   * @param name 名前
   * @param weapon 保持する武器
   * @param magica 固有魔法
   */
  def sealToSoulJem(name: String, weapon: String, magica: String) =
    {
      this.name_ = name;
      this.weapon_ = weapon;
      this.magica_ = magica;
    }
 
  override def toString()=
  {
    "魔法少女 名前" + this.name_ + " 武器:" + this.weapon_ + " 固有魔法:" + this.magica_
  }


でもこれだと正直な話冗長ですよね。
同じメソッドをいくつも書くことになってしまう。

scalaの場合下記のように『引数のデフォルト値』を指定することが可能です。

■PuellaMagi.scala(変更後)

package jp.gr.kmtn.scalatutorial.defaultvalue

/**
 * 「魔法少女」クラス
 *
 * @author Fukushi-
 */
class PuellaMagi() {

  /**
   * 名前を示すフィールド
   */
  var name_ = "";

  /**
   * 保持する武器を示すフィールド
   */
  var weapon_ = "";

  /**
   * 固有魔法を示すフィールド
   */
  var magica_ = "";

  /**
   * 契約を行い、魂をソウルジェムに移して肉体をハードウェアに変換する。
   *
   * @param name 名前
   * @param weapon 保持する武器 デフォルト値=魔法のステッキ
   * @param weapon 固有魔法 デフォルト値=光の魔法
   */
  def sealToSoulJem(name: String, weapon: String = "魔法のステッキ", magica: String = "光の魔法") =
    {
      this.name_ = name;
      this.weapon_ = weapon;
      this.magica_ = magica;
    }

  override def toString()=
  {
    "魔法少女 名前:" + this.name_ + " 武器:" + this.weapon_ + " 固有魔法:" + this.magica_
  }
}


こうすると、デフォルトの値が定義されている引数については、
メソッド呼び出し時に値が渡されなくても自動的にデフォルトで指定した値が用いられるわけです。

実際に使ってみた例を書いてみましょう。
■DefaultValueMain.scala
package jp.gr.kmtn.scalatutorial.defaultvalue

/**
 * 引数デフォルト値確認用メインクラス
 *
 * @author Fukushi-
 */
object DefaultValueMain {

  /**
   * 引数デフォルト値確認用プログラムエントリポイント
   */
  def main(args: Array[String]): Unit =
    {
      val ancientPuellaA = new PuellaMagi
      ancientPuellaA.sealToSoulJem("古代の魔法少女A")
     
      val ancientPuellaB = new PuellaMagi
      ancientPuellaB.sealToSoulJem("古代の魔法少女B", "魔法の剣")
     
      val madoca = new PuellaMagi
      madoca.sealToSoulJem("鹿目 まどか", "薔薇の枝の弓矢", "魔女を全ての時空から生まれる前に消しさる宇宙法則")
     
      Console.println(ancientPuellaA)
      Console.println(ancientPuellaB)
      Console.println(madoca)
    }
}


■実行結果

魔法少女 名前:古代の魔法少女A 武器:魔法のステッキ 固有魔法:光の魔法
魔法少女 名前:古代の魔法少女B 武器:魔法の剣 固有魔法:光の魔法
魔法少女 名前:鹿目 まどか 武器:薔薇の枝の弓矢 固有魔法:魔女を全ての時空から生まれる前に消しさる宇宙法則


こんな感じで、引数を指定しなかった場合、
デフォルトで定義された値が用いられたのがわかると思います。

ただ、これだけだとまだ問題があります。
『途中の引数を省略する場合はどうすればいいのか?』という問題ですね。
とりあえず、それは次回にでも。