• ベストアンサー

ユーザ定義関数にデフォルト引数を複数指定する場合の謎。

いつもお世話になっております。 環境/PHP5 質問内容は単純です。 //ユーザ定義関数を作成 function MyFunc($a,$b,$c=3,$d=4,$e=5){ //処理 } MyFunc(1,2);//$c,$d,$eにはそれぞれデフォルト値が格納される MyFunc(1);//$bの引数が与えられていないのでエラー MyFunc(1,2,100);//$cはデフォルト値ではなく100を優先して格納 $d,$eはデフォルト値 ↑ここまでは分かるのです。 謎なのは、以下です。 MyFuncに与える引数を、 $a=1 $b=2 $c=デフォルト値 $d=200 $e=デフォルト値 としたい場合、 MyFunc(1,2,,200,);//(1)雰囲気ではコレ。でも、これはエラーでしょう。 MyFunc(1,2,3,200);//(2)$cのデフォルト値を手入力($cのデフォルト値が生きてない。$eのみ、デフォルト値を自動格納) 正しいのは、やはり(2)の方法となりますでしょうか。 デフォルト値を設定していても、 上記のようなケースでは、 わざわざデフォルト値を手打ちしなきゃならない、 そんな言語仕様なのでしょうか。 なんとなく違和感を感じましたので、質問をさせて頂きました。 よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

そんな言語仕様です。 hide1978さんのサンプルのように、クラスで実装してしまえば引数順を意識することを無くすことも出来ますし、ユーザ関数で実装するのであれば、 <?php function MyFunc($a, $b, $c=null, $d=null, $e=null){ $c = ($c === null) ? 3 : $c; $d = ($d === null) ? 4 : $d; $e = ($e === null) ? 5 : $e; //以下処理 } ?> としてやれば、いちいちデフォルト値を居れずとも、 <?php MyFunc(1,2,null,200); ?> といったように、デフォルト値を入れたいところをNULLとしてやれば、NULLだった場合にデフォルト値を入れることが出来ます。(結局nullを入れるわけですけども。) 他にもそれにアクセスするためのラッパー関数なんかを用意する方法もあるわけで、 <?php function MyFuncEx($a, $b, $d){ return MyFunc($a, $b, 3, $d, 5); } ?> 第三引数と第五引数はいじらないけど、そのほかはいじるっていうなら、それらだけを引数に持つ関数を作ってやって、オリジナルの関数にそれらを与えてやると。 他にも <?php function MyFunc(){ $args = func_get_args(); } ?> としてやると、MyFuncに与えられた全ての引数を配列として取得できます。 これであれば引数が三つだった場合~、4つだった場合~など、if文などで切り分けてやれば、動的に引数を持つ関数が出来ます。

march4
質問者

お礼

ありがとうございました! また分からないことがありましたら、教えて下さいね^^ 余談ですが、 教えてgooのページビューが速くなりました。 これで、色々とスパスパさばけます。笑

march4
質問者

補足

>そんな言語仕様です。 まずは、この点を確認でき安心しました。 以上で、本問の知りたいことの9割は得られました。笑 でも、補足を。 >としてやれば、いちいちデフォルト値を居れずとも、 この辺りを読んでいる時の私の目は、輝いていました。 「お、来るか、来るか!」 「すごい解決策が、来るか!来るのか!目前に迫っているのか!」 という感じでした(照)。 >MyFunc(1,2,null,200); そして、出ました。 ヌっ、「null」が、潜んでいる!笑 しかも、佇まいが可愛い。笑 やはり、この言語仕様から逃れるのは、 そう簡単なことではないのでしょうね。 それが分かりました。 関係ないですが、 三項演算子を使ったロジックは格好いいですね。 他の件で応用できそうだと感じました。 >(結局nullを入れるわけですけども。) はい。笑 でも、可愛かったので、OK。(謎 >ラッパー関数 ワンクッション置くわけですね。 変換器を噛ませるような意味合いですよね。 >第三引数と第五引数はいじらないけど、そのほかはいじる $c 、$d 、 $e はそれぞれ、 同じくらいの確率で、デフォルトではない値を入れたり入れなかったり、 というようなケースで考えておりますので、 特定の引数に固定値を設定するようなラッパー関数という方法だと、 ちょっと具合が悪そうです。 もし、この方法を選択するとなると、 用意するラッパー関数を何パターンも用意する必要があるので。 なんと言いますか、 「色々面倒なことをするくらいなら、デフォルト値を手っ取り早く手打ちしますよっ」 ということになってしまいそうです。 手打ちというか、 デフォルト値をあえてわざわざ格納するようなロジックというか。 スマートではないけれども、言語仕様だから、しょうがないというような、半ば諦めた目つきで…。 >$args = func_get_args(); これは、何か応用できそうな気がします。 直感ですが。 MyFunc(1,2,3); とした場合、 「3」は、間違いなく$cの値なのですが、 これを、疑わせる処理を書く、なんて感じで。 この「3」は、$cではなく、$dや$eだったりしないの? というような判定処理を書く、みたいな。 (nullを引数に打ち込むことなく) モヤモヤ。 テキトーなことを書き殴ってます。笑 「3」を$cに格納せずに、$cをスルーさせ、 落としどころを、$dや$eに持って行かせる方法を ちょっと考えてみたいですが、 まぁ、言語仕様の通りに扱うことに違和感は感じても、 不便は感じていないので、そこまで掘り下げる話でもない気がしてきました。笑 でも、色々と勉強になりました。 私1人では思いつかないことばかりで、大変刺激的でした!

その他の回答 (1)

  • hide1978
  • ベストアンサー率42% (32/75)
回答No.1

ちょっと質問の趣旨とはズレてしまうかもしれませんが、こういう場合はクラス化してしまうと便利ではないでしょうか。 --[サンプルここから]-- <?php // --クラス定義[ここから]-- class MyFunctions () { // メンバ変数デフォルト値設定 private $a = null; private $b = null; private $c = 3; private $d = 4; private $e = 5; private $ans = null; /* * メンバ関数定義 * メンバ変数aに値をセットする */ public function setValueA ($val) { $this->a = $val; } /* * メンバ関数定義 * メンバ変数bに値をセットする */ public function setValueB ($val) { $this->b = $val; } /* * メンバ関数定義 * メンバ変数cに値をセットする */ public function setValueC ($val) { $this->c = $val; } /* * メンバ関数定義 * メンバ変数dに値をセットする */ public function setValueD ($val) { $this->d = $val; } /* * メンバ関数定義 * メンバ変数eに値をセットする */ public function setValueE ($val) { $this->e = $val; } /* * メンバ関数定義 * $aから$eまでの合計を計算する */ public function main () { if ($this->a != null && $this->b != null && $this->c != null && $this->d != null && $this->e != null) { $this->ans = $this->a + $this->b + $this->c + $this->d + $this->e; return true; } else { return false; } } /* * メンバ関数定義 * $aから$eまでの合計を計算する */ public function getAns () { return $this->ans; } } // --クラス定義[ここまで]-- // メイン処理[ここから]-- $class = new MyFunctions(); $calss->setValueA(1); // メンバ変数$aに1をセット $calss->setValueB(2); // メンバ変数$bに2をセット $calss->setValueE(10); // メンバ変数$eに10をセット $res = $calss->main(); // 計算実行 // 計算結果取得 if ($res) { $answer = $calss->getAns(); } else { $answer = 'Error' } // 結果表示 echo $answer; // メイン処理[ここまで]-- ?> --[サンプルここまで]-- 上記サンプルは$aから$eまでの合計を計算するものです。ご参考までに。

march4
質問者

お礼

>ちょっと質問の趣旨とはズレてしまうかもしれませんが、こういう場合はクラス化してしまうと便利ではないでしょうか。 突然、クラスによる回答でしたので驚きました。笑 回答の汎用性について、ちょっと気になりましたが、 要するに、ケースごとに適当なクラスを作り… というお話ですよね。 デフォルト値どうのこうのというより、 その先の具体的な処理を想定し、 その個々のケースに合ったクラスを作成して対応したらどうか? というアドバイスだったのだと思います。 これは、私の質問で言うところの(2)の方法で、 ひとまず言語仕様に関する考え方は間違ってはいない、 という理解のもと、展開された回答であった、 という解釈でよろしいでしょうか。 で、具体的な処理の1例として、 「$a~$eを合計するサンプル」を挙げて頂いた、 ということなのでしょうね。 私の質問に対し、回答がやや飛躍していたため、 解釈に少々手間取りました。笑 私の上記解釈にもし致命的な誤りがありましたら、教えて下さい。 おそらく、問題ないかとは思いますが。 私のために長いコードを書いて下さり、 どうもありがとうございました。 熱意が伝わってきました。

関連するQ&A