トップページ⇒php
1001コメント362KB

PHPでオブジェクト指向プログラミング

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん2005/04/17(日) 16:55:57ID:iM4mgYnJ
PHP5になって本格的なOOPができるようになったので
PHPによるOOPについて語りましょう。
0666nobodyさん2005/08/28(日) 11:23:32ID:???
境界はそれが速度のボトルネックになるとわかったとき。
通常はする必要なし。
0667nobodyさん2005/08/28(日) 11:59:04ID:???
ナルホド
さんくすちんぽ
0668nobodyさん2005/08/30(火) 10:18:32ID:???
$があってもなくても結局シンボルテーブルを作って参照するんだから
パフォーマンスは関係ない気がする。
あると主張するなら字句解析や構文解析のどういう部分でメリットがあるか
理由を説明して欲しい。

awkとかpythonとか$の必要ないスクリプト言語は現にあるし
それらと比較しても特に$にメリットがあるわけじゃない

php は perl の真似をした
perl は sh の真似をした

それ以上でもそれ以下でもない
0669nobodyさん2005/08/30(火) 10:50:09ID:???
>>662
> あと、$なし言語は
> print "abc $def ghi";
> みたいな真似ができない。

変数の文字列埋め込みなんてフォーマッティングや文字列連結で代替できるじゃん。
0670nobodyさん2005/08/30(火) 12:38:03ID:???
人間にとって
ぱっと見分かりやすいからだろ
0671nobodyさん2005/08/30(火) 13:11:54ID:4hyOkdNt
>662
>$なし言語は
>print "abc $def ghi";
>みたいな真似ができない。

そういうメリットを主張する割には
defineで定義した名前は""内で使うことができないんだよな。
この辺のいいかげんさがPHPの特徴。
0672nobodyさん2005/08/30(火) 21:44:33ID:???
>>670
俺もそう思う。機械にとってどうって事じゃなくて、人にとってどうかだと思う。
ただでさえ素人(俺含む)が多いPHPerにとって、ぱっと見「あ、これ変数ね。」って思えるのは結構重要だと思う。
0673nobodyさん2005/08/30(火) 22:05:46ID:???
おまいらシェルスクリプトって変数名の後に空白入れちゃいけないんですね
まぎらわしいんじゃボケ!
0674nobodyさん2005/08/31(水) 12:00:09ID:???
>>668
php は perl の真似をした 
perl は csh の真似をした 
cshはshの真似をした

の方が正確ではない?

>>669
> 変数の文字列埋め込みなんてフォーマッティングや文字列連結で代替できるじゃん。 

TMTOWTDI。
それらに比べてタイプ量が少なく済み、見通しがいいのは充分メリットだと思うが。

>>671
> defineで定義した名前は""内で使うことができないんだよな。 

そりゃそうだろ……。""の中の[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* を全部パースするのか?
第一""内で使えなくて困る場面なんてそんなにあるか?
0675nobodyさん2005/08/31(水) 12:29:45ID:???
ヒアドキュメント内とかね。
0676nobodyさん2005/08/31(水) 14:00:53ID:???
>>674
Perlの前にはawkが、その前にはsedが入ってくるような。
0677nobodyさん2005/08/31(水) 16:14:20ID:???
>>676
あれ?変数の$の話でしょ?
0678nobodyさん2005/09/02(金) 05:16:07ID:???
みんなdefine()使っているのか。

interfaceで定義したいんだけど
Javaのstatic final変数と違ってconstが使い物にならず。
PHPでJavaのstaticイニシャライザ、インスタンスイニシャライザを
真似することは不可能なんだろうか?
static メソッドを定義してSingletonパターンでなんとか
誤魔化してやるしかないんだろうか。

0679nobodyさん2005/09/02(金) 05:18:08ID:???
>>654
$をつけた理由はテンプレートとして使いたいからかと思われ。
Java用テンプレートエンジンJakarta Velocityは
テンプレート変数は$で始まるようになっている。
0680nobodyさん2005/09/02(金) 05:23:22ID:???
>>662
> >>654
> exit;
> $exit;
>
> $some_func();
> some_func();
>
> print(abc);
> print($abc);
>
> どれも$のあるなしで挙動が違うだろ。あと、$なし言語は
>
> print "abc $def ghi";


$がつくものとして上にあげたJakarta Velocityのようなテンプレートエンジン
として使うメリットはあるが、$なし言語でも
正規表現などが盛り込まれた関数や特殊な関数を使えば
その手の再現は簡単にできる。
JavaのTextFormatというクラスを思い出した。
あれを使い、かつリフレクションAPIを使えば、文字列中に$が現れたら値に変換してから表示する
というメソッドを作ることもできる。リフレクションは重たいけど。
0681nobodyさん2005/09/02(金) 05:30:42ID:???
>>665
これはまずい。
PHPはデフォルトでは配列は値渡しなのか?

Javaやりすぎて、デフォルトでは
配列やオブジェクトは参照渡しのみであり、基本型(プリミティブ型)のみ値渡し
であってこともあり、
PHPでは値渡しなどもできることを忘れていた。

やばい、バグが。


PHPではメソッドの引数にはC/C++のように値渡し参照渡しの設定はできないんだろうか?
Javaでは上と同じように、プリミティブ型のみ値渡しで
他(オブジェクトと配列)は参照渡し。

どうしても値渡しをしたい場合はObject#clone()を使ったり、オーバーライドしたりする。


PHPにはJavaのObject#clone()メソッドに相当する機能cloneもあるんだね。
これでPHPで深いクローニングができるわけか。

0682nobodyさん2005/09/02(金) 05:33:03ID:???
>>656
インタプリタ言語としてつかうならそうだけど、
JavaやC#のようなコンパイラ言語でかつ、VM上でさらにJITコンパイラによって
中間言語をさらにその場でコンパイルするような言語だと
それは最初の開発者によるコンパイルで最適化されるから
どうでもいいような気がする。

Zendエンジンなんてものもあるけど、タダで使えればねえ。
0683nobodyさん2005/09/02(金) 07:20:11ID:MBSmrOid
>>681
ごめん、何が言いたいかよく解らん。。
取り敢えず疑問は解決したの?
0684nobodyさん2005/09/02(金) 09:20:10ID:???
>>679
歴史的に見れば、裸の文字リテラルや予約語と衝突しないのが当初の目的でしょ。
shで裸の変数を許したらコマンドや引数はどうやって指定すりゃいいんだ。

あとは$があるとパーサが変数かどうかの判定に困らないので、文法の幅が広がる。
phpのexitみたいな括弧なしの言語構造や、Perl関数の戻り値にスカラが指定できるような
芸当は$なし言語だと厳しいでしょ。
0685nobodyさん2005/09/02(金) 09:22:02ID:???
exitは別に厳しくないか。exitって名前の変数が使えなくなるだけだな。
0686nobodyさん2005/09/02(金) 11:57:33ID:???
>>681
> PHPはデフォルトでは配列は値渡しなのか?
値渡しだけど、配列の要素を書き換えない限り、内部的には配列はコピーされないのでパフォーマンス的には参照渡しと同じ。
文字列やオブジェクトも同様。

> PHPではメソッドの引数にはC/C++のように値渡し参照渡しの設定はできないんだろうか?
&をつければ参照渡し。その点はC++に似てる。
C++では配列ならC式の参照渡し(アドレスの値渡し)で十分だけど。

とりあえず疑問文にだけコメントしといた。
0687nobodyさん2005/09/03(土) 00:10:51ID:???
http://www.zend.com/zend/art/ref-count.php
0688nobodyさん2005/09/03(土) 09:36:19ID:JcQXpRDz
最近PHP5に移行したんだが
たとえば。クラスtest,
メソッドtest($t){$this->t}と定義した場合
$test= class test;
でメソッドのひきすうに10を渡した場合
$test->test(10);
これでなにも表示されないんですね・・・なんかつかいずらい
いちいちメンバーを定義して
public $tみたいに・・・めんどくせえ・・・

0689nobodyさん2005/09/03(土) 10:52:27ID:???
>>688
public $t;書いてもそのままじゃ何も表示されないとおもうけど。
echoはないわ、$this->tに値いれてないわ。おかげで主張の内容がさっぱりわからん。
まずどの言語から移行したわけ?メンバ定義なしでメンバを使える言語ってまさか・・・?
0690nobodyさん2005/09/03(土) 11:17:01ID:???
>>688
その前にメソッド名がクラス名と同じならコンストラクタになるんじゃなかったか?
0691nobodyさん2005/09/03(土) 12:22:13ID:???
>>690
php5では
function __construct() { }
が優先される
<?php
class test {
function __construct() {
echo "testクラス作成<br>\n";
}

function test($t) {
echo $t;
}
}
$test = new test();
$test->test(10);
?>
こんなことも出来る
0692nobodyさん2005/09/03(土) 16:19:09ID:???
>>691
__construct()が優先されるけど、書いてないならこの場合test($t)が呼ばれるよ。
んで、インスタンス化した際に引数つけてないとWarningがでる。
>>688で書いてる、
$test= class test;
って書き方初めて見たのだが、それエラーするだろ?
それとも俺はPHP5しか知らないのだけど、4ではその書き方出来るの?
0693nobodyさん2005/09/03(土) 16:46:21ID:JcQXpRDz
>>688だが・・すまんまちがったソースかいてもうた

俺がいいたかったのは
class test;
{ pubclic funciton tes($a);
{
echo($this->a);
}}
で
st= new test();
ここでメソッドをよびだした場合
st->tes(10);なにも記述しなてくて
つまりメソッドの場合$this->aってできないんだな
public $a; $this->a=$a
みたいな・・二度手間だな・・・まぁいきなり$aならこれでも表示するんだが
本みるとこの二度手間をしてる・・


0694nobodyさん2005/09/03(土) 16:47:21ID:???
なんかコンストラクタの話になってるが>>688は
> $test->test(10);
と書いているので、コンストラクタの話題を意図していたわけじゃないんだろうけどな。

>>692
> 4ではその書き方出来るの?
んなわきゃないw
PHP Parse error: parse error, unexpected T_CLASS in (ry
極めて真っ当なエラーですな。
0695nobodyさん2005/09/03(土) 17:01:56ID:???
>>693
その本で何を解説してるのか知らないが、大方
・プロパティ名とメソッドの引数名は同じでも問題なし
・public $a と $this->a の「a」は同じ変数を表すが tes($a) の「a」は全く別の変数
ってな感じの内容じゃないの?
どこが二度手間なわけ?
0696nobodyさん2005/09/03(土) 17:35:38ID:???
>>693
PHPの前に日本語勉強してくれと思ったのは俺だけ?
0697nobodyさん2005/09/03(土) 18:15:04ID:JcQXpRDz
>>695
てことは
クラスの中に
メソッド pubulic funciton hell($a){ echo($a."さんこんにちは");}
こういう使い方はできるんだね。現にやったらできたけど
なんかPHP5の本ではさやたら$this->
って感じでやってるから。
PHP5の本どうでもいいけど少なすぎ><
0698nobodyさん2005/09/03(土) 18:18:07ID:JcQXpRDz
つづきだけど
本ではさ
public $a;
pubulic funciton hel($a){
$this->a=$a
echo($this->a."さんこんにちは")}
みたいな使いかたをしてたから
なんでこんな二度でまをふんでるんだろうかと
本がわるいのかもしかして
0699nobodyさん2005/09/03(土) 18:22:35ID:JcQXpRDz
しかしおまえらいいやつばかりだな・・
俺みたいなやつの質問にこたえてくれて
会社でPHPつかえるやついなくてな、皆javaばかりで
おれだけPHPだから肩身せまくてな
これからもよろしくたのむよ
0700nobodyさん2005/09/03(土) 18:53:52ID:???
>>693,697
$aをメソッド内のローカル変数として使いたいのか
それともフィールド変数として他のメソッドからも使いたいのか
どっちが目的なのかわからん。
0701nobodyさん2005/09/03(土) 19:00:47ID:???
>>699
この程度の内容にPHP4、PHP5、Javaで違いはないんだが(書式以外で)。
オマイがカスすぎて他の社員から相手にされてないだけではないのか。
0702nobodyさん2005/09/03(土) 19:15:26ID:???
>>699
>会社でPHPつかえるやついなくてな、皆javaばかりで
>おれだけPHPだから肩身せまくてな

オマエ、どうみてもPHP使えないだろ? 下手するとPHPだけじゃなくプログラミング自体素人か。
Javaは絶対習得できそうにないからPHPでもやらせとけ、って感じしかしないのだが。
0703nobodyさん2005/09/03(土) 19:37:49ID:fR+7vSEm
というかアレだ。
本の読み方を間違ってる。
0704nobodyさん2005/09/03(土) 19:39:05ID:JcQXpRDz
まぁな
もともと営業ではいったからな
プログラミング歴は3週間目だ。
これで月給38万ももらってていいのか。
0705nobodyさん2005/09/03(土) 20:12:15ID:???
>>704
営業で入ったにしても日本語が下手すぎるね。
まぁ給料貰えるうちに頑張れ。

なんでthisを多用するかって事だけど、先の例だと
setterっぽく使いたかったのかな?変数publicだけど・・・。
その本を読み進めて行くと、多分その疑問は解凍されると思うよ。

0706nobodyさん2005/09/03(土) 23:51:44ID:???
http://www.thinkit.co.jp/free/tech/3/8/1.html
インピーダンスミスマッチについてどうお考えですか?

仕事でPHPでオブジェクト指向で進めようとしていますが、
PHPの効率のよさはオブジェクト指向ではないやり方によるものだった
ってことはありませんか?

0707nobodyさん2005/09/03(土) 23:59:36ID:???
>>704
営業で入って、プログラミング歴3週目で、>>688 で書いている
"最近PHP5に移行したんだが" が激しく一致しない。。。
0708nobodyさん2005/09/04(日) 01:10:09ID:???
>>707
3週間前PHP4の本渡されて勉強した後、最近新たにPHP5の本渡されて勉強しはじめたんでないか?
彼の中ではすでに「最近PHP5でクラスを自作しました」とかになっていると思われ。

0709nobodyさん2005/09/04(日) 02:03:40ID:???
>>706
規模による。
0710nobodyさん2005/09/04(日) 03:05:09ID:???
>>704
いい身分だな。
何も教えてやりたい気分も萎えそうだが
オブジェクト指向を理解していない奴と一緒にソフト開発することほど
ウザイことはないから少しだけ教えてやる。
0711nobodyさん2005/09/04(日) 03:05:42ID:???
>>698
それはお前がつまらんサンプルに踊らされてるだけだ。
0712nobodyさん2005/09/04(日) 03:07:29ID:???
>>697
PHP5でオブジェクト指向ををやるのに本が少なすぎる?
ならJavaの本を買え。
結城浩の「Java言語で学ぶデザインパターン入門」
これ嫁。これ読めばPHP5で無理矢理オブジェクト指向するよりも
オブジェクト指向は素早くすんなり理解できる。
何と言ってもオブジェクト指向といえばJavaと言われているくらいだからな。
0713nobodyさん2005/09/04(日) 03:12:09ID:???
>>698
純粋論者はインスタンスフィールド$aをprivateにすべきだと主張する傾向にあることをよく覚えておけ。
そのときは$aに対するgetter/setterを定義するることをお忘れ無く。
PHP5からは__getや__setなんてものもあるらしいな。
どんなメリットがあるのかわからんので
自力でgetA(), setA($a)を定義してはいるが。

メソッド引数で定義されている$aはローカル変数で
フィールドの$aとは異なる。
そのときの重複を避けるために$this->aという記法を用いる。
0714nobodyさん2005/09/04(日) 03:14:50ID:???
PHP5では
Javaのfinalに相当する最初の一回しか代入を許されない変数を定義できないのだろうか?
でないと不変クラスを作れない予感が。


0715nobodyさん2005/09/04(日) 03:16:30ID:???
PHP5ではオブジェクト指向言語としての
機能が強化されてもnamespaceが使えないのが非常に残念だ。
Facadeパターンなどを実現しづらい。Javaですっきりと実現できる
デザインパターンがPHP5ではあまりにも中途半端でアクセス権の管理があまりにも杜撰になる。
0716nobodyさん2005/09/04(日) 04:32:10ID:???
PHPでアクセス権云々考えてもしょうがないだろ。
PEARみたいな公式の出すらPHP4との互換性保持のため
ほぼ全てのフィールドがvar宣言。メソッドも同様。
0717nobodyさん2005/09/04(日) 06:15:04ID:???
PHPプログラマはJavaに毒され過ぎ。
0718nobodyさん2005/09/04(日) 08:21:13ID:???
Perlもあんなにヘボいオブジェクト指向でがんばってるんだから、
無理にJava目指すことは無いんじゃないかな。

OOPを知りつつ、OOPの考え方で
OOPじゃない簡単な実装だってできるだろうし。
0719nobodyさん2005/09/04(日) 08:23:48ID:???
>>718
> OOPじゃない簡単な実装だってできるだろうし。
理論ガチガチじゃない簡単な実装
に自己訂正。
0720nobodyさん2005/09/04(日) 08:27:14ID:???
PHP はパチ物臭くてナンボだろ
0721nobodyさん2005/09/04(日) 10:11:49ID:???
>>714
できるようだが。
ttp://www.php.net/manual/ja/language.oop5.final.php
0722nobodyさん2005/09/04(日) 17:13:11ID:???
>>716
PEAR::MDB2というのがあるが、
今ベータ版。
MDB1がPHP4対応であるのに対してMDB2はPHP5対応。
よってこれからのPEARはPHP5によってすべて生まれ変わる。
0723nobodyさん2005/09/04(日) 17:20:23ID:xhmaGAtH
>>721
あのーfinalなクラスやメソッドを定義できるのは知ってるんですけどー
やりたいことはfinalなフィールド(メンバ変数、プロパティ、属性)やローカル変数を定義したいんですけどー

constしか使えないんですかぁ?
const CONSTANT = 'aa';
とかはできるんだけどさあ。

const CONSTANT2;
と宣言だけしておいて

コンストラクタで
public __construct(Type $constant){
 $this->CONSTANT2 = $constant;
}
と後から代入するってことができないんですけどー

こういうこともできなくて困ってるんですけどー
const CONSTANT3 = CONSTANT2.'連結'
0724nobodyさん2005/09/04(日) 17:23:35ID:???
こういうこともできなくて困ってるんですけどー

pulic void doMethod(final Type type){
 type = "aa"; //typeはfinal宣言されているので
          //あとから代入するとエラーになるように、誤作動防止機能
          //として使える。
}


これをPHP5でやると?

pulic function doMethod(constant Type $type){
 $type = "aa"; //typeはfinal宣言されているので
          //あとから代入するとエラーになるように、誤作動防止機能
          //として使える、はずなのだが。
}

見事にエラーですか。
困っちゃったねえこりゃ
0725nobodyさん2005/09/04(日) 17:24:52ID:???
>>718
そこでPerl6ですよ。
ParrotVirtualMachineといい、コンパイラといいバイトコードといい
もろJavaのパクリですが。
0726nobodyさん2005/09/04(日) 21:26:38ID:???
>>724
Singletonでなんとかならんか?
ってか、phpならそうやって使うのが普通だと思うが?
なぜjavaに拘る.

# finally欲しいなぁ
0727nobodyさん2005/09/04(日) 21:35:22ID:???
>>726
同意。
Javaはコンパイル型。PHPはインタプリタ型。
だから同じ書き方・動作じゃないのは当たり前なんだけど。

例えば Javaでいう Interface みたいのを
スクリプト言語に入れるのは、なんか違うよね。
そういうのはコンパイル型の言語で素直にやりなよ、ということ。
0728nobodyさん2005/09/04(日) 23:58:21ID:???
>>725
それだったらGroovyとかでも良いような気がするんだけどねー
0729nobodyさん2005/09/05(月) 03:40:43ID:???
>>727
うっせー
仕事でPHPを使わされとるんじゃい!
PHPはJavaより使いにくすぎなんじゃい!
0730nobodyさん2005/09/05(月) 04:03:31ID:???
Java2PHPなる
JavaソースをPHP5ソースに変換するツールはおらぬのか?
0731nobodyさん2005/09/05(月) 21:58:26ID:???
>>727
なんでInterfaceがいらないの?
子クラスにメソッドの実装を強制できないじゃん。
0732nobodyさん2005/09/05(月) 22:06:33ID:???
>>731
いらないんじゃなくて、ナンセンスだってことでしょ。
スクリプト言語なのに、メソッド実装を強制するような事が。
実行時に文字列を読み込んで、
その場でインタプリタがクラス作っちゃうような事もできるのに。

Interfaceみたいのは、別にあっても良いと思うけど。
速度に問題出なければ。
0733nobodyさん2005/09/05(月) 22:30:28ID:???
思うのだが、PHPでOOPしようとするのは、
Java使いがPHPを使う場合、またはPHP使いがJavaを学ぶ為って感じがする。
自分がそうだったし。
PHPでOOPだのDIだのなんだのすると速度的にかなりマイナスだしね。
0734nobodyさん2005/09/05(月) 22:42:44ID:???
ポイントは、コンパイラかインタプリタかということよりも、
静的型付けか動的型付けかということのような気がする。
0735nobodyさん2005/09/05(月) 23:35:49ID:???
正解。ポリモルフィズムとか全然意味無い。
0736nobodyさん2005/09/06(火) 00:39:18ID:???
Rubyの「実装されてないメソッドがコールされたら、こいつに委譲する」ってのが楽なんだよなぁ
0737nobodyさん2005/09/06(火) 01:00:02ID:???
それはPHPでもできるだろ。
0738nobodyさん2005/09/06(火) 01:11:32ID:???
__callや__set、__get、__autoloadは効果的に使ってみたい機能だな
0739nobodyさん2005/09/06(火) 01:17:11ID:???
王道はプロパティを全部privateかprotectedにして、セッタ/ゲッタとか、
setXXX(), getXxx() を__call()でオーバーロードするとか、そんな感じですかね。
DAO設計するときに役立ちそう。
0740nobodyさん2005/09/06(火) 03:01:57ID:???
__autoloadはオーバーライドできないのがネックだよなあ。
dev-mlでもそのへんの改善案を検討しているみたいだけど。
基本的にPHPのマジックメソッドはどれもちょっと抜けてて使いにくい。
0741nobodyさん2005/09/07(水) 12:41:40ID:???
>>732
おまい、デザインパターンをなめてるでしょ。
interfaceが無いと多重継承ができないんじゃYO!

0742nobodyさん2005/09/07(水) 12:48:27ID:???
>>738
require()が無駄にリストアップされてしまう問題を
__autoload()によって解決できるとおもったらそれできんのかい?
>>740もオーバーライドができないってことは、かなり痛すぎる予感。

Javaの真似をして
とりあえず、すべてのクラスの頂点たるObjectクラスを実装して、
そのクラスにとりあえず__autoload()を
入れておくってか。

以後、すべてのクラスは、継承宣言をする予定がないときは、
かならずObjectクラスを継承するように予定変更する、と。
で、ObjectクラスにはJavaのObjectと同じように、
hashcode(), equals(), finalize(), wait(), notify()などを実装する。
少なくとも、equals()は重要。

Comparableインターフェースなども作っておく。でcompareTo()メソッドも
実装できるように。Cloneable, Serializableインターフェースも。


__autoload()を無理矢理オーバーライドするなら、
これしかないか?

__autoload()を他のメソッドでラップし、そのメソッドをサブクラスオーバーライドする。
でオーバライドしたらまたそのサブクラス内で__autoload()を実装し、オーバーライドした
メソッドを呼び出す。

っていうやりかたはうまくいかんか?
0743nobodyさん2005/09/07(水) 13:08:31ID:???
>>741
PHPで多重継承が必要な場面に遭遇したことないけど。
それが>>732の言わんとしてることじゃないの?

>>742
__autoloadのラッパ・・・?それじゃ__autoloadの意味ないじゃん。
ファクトリメソッド作るなら、そのメソッド内でrequireしたほうが話は早いわな。
とりあえず何を主張したいのかが不明瞭。
>>738と>>740への批判みたいなことを言いたいのだろうか?
0744nobodyさん2005/09/07(水) 16:59:36ID:???
>>741
多重継承しないように設計すれば良いだけでしょ。
Javaでしかデザインパターンしたこと無いのかも知れないけど…。
0745nobodyさん2005/09/07(水) 21:56:51ID:???
多重継承しないようにすればいいっておい、
委譲や集約だけに任せるってのかい。
そっちのほうがもっとナンセンスに見えることもないか?

デザインパターンでも多重継承つかったサンプルが沢山あるのに。

それに、オブジェクトをディープコピーできるようになることを示すCloneableインターフェース、
オブジェクトを直列化できることを示すSerializableインターフェース、
これらが使えんだろ。
こういうインターフェースを定義したい場面ってのが結構ある。

あるクラスを継承したいが、すでに他のクラスによって継承されているので
これ以上継承できない、っていうとき、片方のクラスがインターフェースになっていれば助かる。

とくにマーカーインターフェースは使える。
>>732はメソッド実装を強制するためだけにインターフェースを使うつもりでいるらしいが、
マーカーインターフェースはメソッドなんかいらない。
Serializableはメソッドなんか一つもない。まさにクラスにマーカーをつけるかのように
インターフェースを実装できる。
このように、一つのクラスに、継承しながら複数のインターフェースを実装したい場合があるときに、
インターフェースは役に立つ。

デザインパターンの本を良く読んでいるならインターフェースを使ったサンプルはよく見かけると思うが。
インターフェースは便利だから使う。抽象クラスだけでは限界があるとき、
非常に役立つ。
無計画に使いすぎるとインターフェースの乱立が生じてとんでもないことにはなるが。
使い方さえ気をつければ非常に使える。

それから、定数を定義するときもインターフェースをよく使う。
実装はしないがタダ定数を置くだけ。define()を使えという意見もあるが、インターフェース名::定数名
という構文規則が守られちょっとわかりやすくなる。
0746nobodyさん2005/09/07(水) 21:59:17ID:???
PHP5ではすでに抽象クラスも定義できるようになってしまった以上、
インターフェースも使えないのはなにか違和感がある。
ここでクラスだけにしたら、クラスに多重継承させることを許してしまう。
というか、クラスで多重継承ができることを許さないといけなくなる。
そうするとC++のような混乱が生じ、ダイヤモンド継承とかわけのわからんことになる。
だからインターフェースは必要なんだと。
0747nobodyさん2005/09/07(水) 22:15:56ID:???
そこまでやりたきゃPHP使わんでJava使えば良い。
デザパタは大事だけど、PHP採用してるような現場でそこまで厳密なOOPが必要か?
とも思う。
現状のPHPが中途半端な状態にあるのは分かるけど、
中途半端なら回避すれば良いだけでしょ。

仕事でどうしてもPHP使えと言われていて、PHPの今の実装はこうです。となってる。
デザパタ知ってるなら、その考えを使って、
いま組めと言われている言語にあった、無理の無い設計をするのが普通じゃないのかな。
うまく骨抜きにして言語に合うように実装する。そんだけだろ。
0748nobodyさん2005/09/07(水) 22:22:32ID:???
コンパイル言語ならコンパイラが最適化してくれるから
「プログラミングで注意すべき部分を冗長にマーキングする」でかまわんけどなぁ・・・

ZendEngineにキャッシュが搭載されるのはPHP6からだっけ?
0749nobodyさん2005/09/08(木) 00:05:46ID:???
>>746
うむ。「インターフェイスがないと多重継承ができない」とか聞くと違和感覚える。
普段どんなインターフェイスの使い方してるのか気になったりする。
0750nobodyさん2005/09/08(木) 00:42:45ID:???
Interfaceがいらないとか言ってる奴はデザパタとか知らんのだろうな。
Adapterパターンとかな。(代替手段として委譲するのもあるがな)
0751nobodyさん2005/09/08(木) 01:01:24ID:???
interfaceは多重継承の代替案ではない
0752nobodyさん2005/09/08(木) 02:07:18ID:???
PHPのinterfaceは、そのinterfaceの実装クラスを作る人には役に立つ。
ところがそれら作られたものを使う人(クラス)には役に立たない。
0753nobodyさん2005/09/08(木) 02:38:21ID:???
>750
代替って言うか常に委譲の方で良いじゃん。
interface不要って事だ。
0754nobodyさん2005/09/08(木) 02:49:08ID:???
こういう事でしょう。

execute()を持つAというinterface
それを実装したクラスB1とB2が有ったとする。

で、利用するコード
$a[] = new B1();
$a[] = new B2();
$a[] = new C1();
foreach ($a => $obj) {
$obj->execute();
}

ここでC1はたまたまexecute()を持つAを実装でないクラス。
PHPはこれでエラーが起きない。
0755nobodyさん2005/09/08(木) 02:55:41ID:???
そもそもコード中にAというクラス名が一度も出てきていないから
何をしたいのかも明確にできない。type hintingみたいな機能もあるけど
Javaと違ってmainメソッドを必ずしもクラスにする必要は無いわけだし。
0756nobodyさん2005/09/08(木) 03:33:10ID:???
>>755
まあわかってやれよ。こういうことだろ?
interface A { public function execute(); }
class B1 implements A { public function execute() { ・・・ } }
class B2 implements A { public function execute() { ・・・ } }
class C1 /* doesn't implement A */ { public function execute() { ・・・ } }
$a = array(new B1(), new B2(), new C1());
foreach ($a as $obj) $obj->execute(); // interface Aなんて初めからあってもなくても結局変わらん

つまり、PHPのinterfaceはインスタンスの型を制限する役割は全く果たせないってこった。
ただJavaライクな文法があれば、Javaに慣れている人間同士で意思の疎通や理解がしやすくなり、結果的にデザパタも組みやすくなるって面もある罠。
その点では大きな利点といえる。
しかし、飽くまで可読性・保守性に関する利点であって、PHPの言語仕様上の利点ではない。
現にPHPでデザパタは多くの場合、単に「通念的」にしか実装できないことが多いが、その限りでは文法上どんなデザパタもinterfaceなしで実装できることになる。
0757nobodyさん2005/09/08(木) 08:45:11ID:???
>>754
まあ PHP 的には以下のようにするのが限界かな。

foreach ($a => $obj) {
if ($obj instanceof A) {
$obj->execute();
}
}

もしくは duck-typing な感じで、

foreach ($a => $obj) {
if (method_exists($obj, 'execute')) {
$obj->execute();
}
}

とか。
07587572005/09/08(木) 08:54:45ID:???
よく考えてみたら、>>754 のコードを Java で書いた場合、

■$a をコレクションにして Iterator を使った場合

while ループの中で A obj = (A) iterator.next(); とした時に
C のインスタンスが ClassCastException で引っかかる

■$a を A の配列にした場合

配列に C1 のインスタンスを代入しようとした時点でエラー

となるわけで、どっちかっつーと PHP の扱い方のほうが便利じゃない?
0759nobodyさん2005/09/08(木) 10:41:54ID:???
>>758
だろ。

ってことは、interfaceの存在意義は何なんだ?
0760nobodyさん2005/09/08(木) 10:46:30ID:???
>>758
だからその「便利じゃない」って点こそが肝なんだよな、結局。
書けるコードに制限を設けることで意図を明確にできるわけで。
0761nobodyさん2005/09/08(木) 11:52:57ID:???
つまりinterfaceはPHPの型宣言なしという言語仕様に馴染まないって事でしょう。
0762nobodyさん2005/09/08(木) 13:09:48ID:???
>>756
インスタンスの型を制限する役割はないといっても
メソッドに引数で制限できるから
インターフェースはわりと使えるもんだよ
0763nobodyさん2005/09/08(木) 15:49:09ID:???
>>754のコードを意図的に書きたい場合、
JavaならばC1の書き直し、
状況によってはinterface A自体の見直しも必要になってくる。
AやC1が外部のライブラリならその修正も困難。
(まあ、そのためにAdapterパターンがあるのかもしれないが
Adapterパターンの多用は冗長になるなどの欠点をしばしば指摘される。)

そういう点でPHPのような動的な型付け言語は柔軟性があるのだと思う。
でも>>754のコードが意図的なのかどうかというのを
コメントなしに伝える事が不可能な点が問題。
メソッドの引数で伝えるのは状況が限られる。

柔軟性か信頼性かって事だ。
0764nobodyさん2005/09/08(木) 18:08:42ID:???
>>763
それはJAVAを理解してないだけでは
0765nobodyさん2005/09/08(木) 18:58:07ID:???
そうなの?具体的なことがないと何とも反論できん。
■ このスレッドは過去ログ倉庫に格納されています