SlideShare uma empresa Scribd logo
1 de 59
Baixar para ler offline
copyright(c) 2013 kuwata-lab.com all rights reserved.
PHPとJavaScriptにおける
オブジェクト指向を比較する
makoto kuwata <kwa@kuwata-lab.com>
http://www.kuwata-lab.com/
2013-09-14 (Sat)
PHPカンファレンス2013
【更新履歴】
・2013-09-17: 大幅に加筆修正
copyright(c) 2013 kuwata-lab.com all rights reserved.
本発表について
• PHPでのオブジェクト指向の仕組みを理解する
• JavaScriptでの(同上)
• Class BaseとPrototype Baseの違いを理解する
• オブジェクト指向言語の基礎知識があること
(クラス、インスタンス、メソッド、etc)
• JavaScriptを書いた経験があること
• 独自の解釈が登場!自分で考えて判断を!
【目的】
【前提】
【注意】
copyright(c) 2013 kuwata-lab.com all rights reserved.
オブジェクト指向機能の仕組み
(PHP編)
Internal Mechanism of OOP in PHP
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
オブジェクト指向機能の肝であるメソッド呼び出しの仕組みを説明します。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
変数はポインタであり、インスタンスオブジェクトを参照しています。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
インスタンスオブジェクトには、クラスオブジェクトへの隠しポインタがあります。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
クラスオブジェクトは、メソッド探索テーブルへのポインタを持っています。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
メソッド名をキーにしてメソッド関数を探し、もしあれば実行します。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
もしメソッド名が見つからなければ、親クラスを ります。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
そこでも同じように、メソッド探索テーブルを使ってメソッドを検索します。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
最後にルートクラスでもメソッドが見つからなければ、実行時エラーとなります。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
function () {
.....
}
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
このように、メソッドは呼び出し時に「探索」される点が、関数と決定的に違います。
オブジェクト指向の柔軟性はこれのおかげですが、関数より遅い原因でもあります。
copyright(c) 2013 kuwata-lab.com all rights reserved.
インスタンス変数とインスタンスメソッド
クラス
x: 15
y: 25
メソッド表
m4
m2
m3
Z: 456
function () {
.....
}
インスタンス変数はインスタン
スのもの(共有されない)
インスタンスメソッドは
クラスのもの(共有される)
メソッド関数
インスタンス
x: 10
y: 20
x: 30
y: 40
copyright(c) 2013 kuwata-lab.com all rights reserved.
is-aポインタ
所属するクラスオブジェクトを指す隠しポインタ◆
つまりインスタンスは、「自分が何者かを知っている」
x: 10
インスタンス クラス
変数
y: 20
is-a ポインタは
is-a 関係を表す
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド探索テーブル
メソッドテーブル
m1
m2
m3
function () {
echo "hello";
}
function ($x) {
return $x + 1;
}
クラス
メソッド名 + メソッド関数へのポインタ◆
メソッド名をキーにして、メソッド関数が動的に検索される
(注)
(注)正確には「メソッドシグニチャ」(詳細は省略)
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッドオーバーライドと parent 呼び出し
変数
インスタンス
クラス
クラス
x: 10
y: 20
メソッド表
メソッド表
m4
m2
m3
m3
m1
m2
Z: 123
Z: 456
メソッド関数
function () {
.....
}
function () {
.....
}
同じ名前で別の関数を
登録するのがオーバーライド
自クラスをスキップして
親クラスから探索するのが
parent 呼び出し
メソッド関数
copyright(c) 2013 kuwata-lab.com all rights reserved.
オブジェクト指向機能の仕組み
(JavaScript編)
Internal Mechanism of OOP in JavaScript
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
JavaScript におけるメソッド呼び出しの仕組みを説明します。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
変数はオブジェクトを指しています。そこにプロパティがあるかを調べます。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
指定されたプロパティがなければ、別のオブジェクトをたどります。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
見つかったプロパティが関数であれば、メソッドとして実行できます。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
見つからなければ、さらに別のオブジェクトをたどって、
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
同じようにプロパティを探します。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
最後までたどっても見つからなかれば、(JSでは) undefined が返されます。
copyright(c) 2013 kuwata-lab.com all rights reserved.
メソッド呼び出し
変数
オブジェクト
オブジェクト
オブジェクト
x: 10
y: 20
function () {
.....
}
m2:
Z: 456
関数オブジェクト
function () {
.....
}
m1:
m2:
関数オブジェクト
このように、JavaScriptの動作もPHPとよく似ています。ただし、クラスやメソッド
探索テーブルは存在せず、すべてオブジェクトで済ませているのが特徴です。
copyright(c) 2013 kuwata-lab.com all rights reserved.
__proto__ プロパティ
プロパティが自分にないときに探しに行く先◆
is-a ポインタに相当するが、任意のオブジェクトを自分で指定可能
height: 15
オブジェクト変数 obj
__proto__:
height: 0
オブジェクト
width: 0
__proto__:
width: 30
color: 'red'
obj.color	 ==	 'red'
(注)
(注)IE9 以前では利用不可
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプチェーン
プロパティが見つかるまで __proto__ をたどる◆
最後までたどっても見つからなければ undefined を返す
y: 20
オブジェクト
__proto__:
x: 10
オブジェクト
y: 10
__proto__:
x: 0
オブジェクト
y: 0
__proto__:
z: 0探してるのが
「y」ならこれ
が使われる
「x」ならこれ
が使われる
「z」ならここ
まで探しにくる
copyright(c) 2013 kuwata-lab.com all rights reserved.
コンストラクタ
function	 Foo(x)	 {
	 	 this.x	 =	 x;
}
Foo.prototype.value	 =	 100;
Foo.prototype.hello	 =	 function()	 {	 ...	 };
prototype:
関数オブジェクト
name: 'Foo'
__proto__:
変数 Foo
関数オブ
ジェクト
value: 100
hello:
__proto__:
オブジェクト
__proto__ と .prototype は
別であることに注意
copyright(c) 2013 kuwata-lab.com all rights reserved.
new 演算子
var	 obj	 =	 new	 Foo(123);
obj.hello();
x: 123
オブジェクト
__proto__:
変数 obj
prototype:
関数オブジェクト
name: 'Foo'
__proto__:
変数 Foo
関数オブ
ジェクト
value: 100
hello:
__proto__:
オブジェクト
空オブジェクトを生成、
__proto__ を設定、
コンストラクタを適用
copyright(c) 2013 kuwata-lab.com all rights reserved.
__proto__ と prototype の違いがわかりません!
Foo.__proto__ は、Foo という(関数)オブジェ
クトのためのもの
◆
new で新規作成するオブジェクトには、何も関係しない
Foo.prototype は、new で新規作成するオブジェ
クトのためのもの
◆
Foo 関数自身のプロトタイプチェーンには、何も関係しない
copyright(c) 2013 kuwata-lab.com all rights reserved.
クラスベース (PHP) と
プロトタイプベース (JS)
Class Base v.s. Prototype Base
copyright(c) 2013 kuwata-lab.com all rights reserved.
北の賢者曰く
プロトタイプベースにいくつかの制約を加えたのが
クラスベースである。
つまり、クラスベースはプロトタイプベースのサブ
セットである。
“
”
http://sumim.no-ip.com/wiki/493
(「超約」してるので原文を確認のこと)
by sumim
copyright(c) 2013 kuwata-lab.com all rights reserved.
is-a ポインタ v.s. __proto__ プロパティ
$obj->isa	 =	 new	 Other();	 	 	 //	 できない
is-a ポインタは、プロブラマが変更できない◆
そもそもプログラマには見えない
obj.__proto__	 =	 new	 Other();	 	 	 //	 できる!
__proto__ プロパティは、自由に変更できる◆
任意のオブジェクトを設定できる
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプベース + 制約 = クラスベース
クラスベース (PHP) プロトタイプベース (JS)
探索
ポインタ
ポイント対象
ポインタ先
クラスチェーン プロトタイプチェーン
is-a ポインタ __proto__ プロパティ
クラスオブジェクトのみ 任意のオブジェクト
変更不可 変更可能
制約がない制約がある!
“プロトタイプベースにいくつかの制約を
加えたのがクラスベースである。”
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプベース ⊃ クラスベース
プロトタイプベース
クラスベース
両者は、排他関係ではなく包含関係◆
制約がある分、クラスベースのほうが「狭い」
“クラスベースはプロトタイプベースの
サブセットである。”
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプベースの
応用パターン
Advanced Pattern of Prorotype Base
copyright(c) 2013 kuwata-lab.com all rights reserved.
設定ファイル用オブジェクト
default (共通)
共通する設定を一元管理◆
開発用と本番用は差分だけを管理
development (開発用)
__proto__:
user: "your-name"
production (本番用)
__proto__:
user: "wpadmin"
pass: "bh#un?j9"
__proto__:
host: "localhost"
port: 3306
user: ""
pass: ""
db: "wordpress"
copyright(c) 2013 kuwata-lab.com all rights reserved.
追記型オブジェクト
一度公開したオブジェクトは一切変更しない◆
変更するかわりに、差分だけのオブジェクトを作り (注)、その
__proto__ にもとのオブジェクトを設定。
(注) 値の削除は、undefined で表現する。
__proto__:
color: "red"
version: 3
__proto__:
height: 125
version: 4
__proto__:
width: 55
version: 2
__proto__:
height: 120
width: 50
color: "pink"
version: 1
created: "09/14"
copyright(c) 2013 kuwata-lab.com all rights reserved.
DCI (Data, Context, Interaction), Decorator Pattern
__proto__:
name: "○×社"
addr: "東京"
phone: "03-..."
created: "09/14"
__proto__:
納期問合せ()
発注処理()
発注先 (Role)
__proto__:
納期回答()
受注処理()
受注先 (Role) 取引先 (Player)
インスタンス単位での拡張や追加がとても自然◆
「差分プログラミング」がクラス単位ではなくインスタンス単位に
「受注先」と
して機能する
「取引先」
「受注先」かつ
「発注先」であ
る「取引先」
(あとで詳しくやります…)
copyright(c) 2013 kuwata-lab.com all rights reserved.
よくある誤解
プロトタイプベースは面倒、クラスベースのほ
うが簡単で便利!〔PHP派による誤解〕
◆
制約がない分、プロトタイプベースのほうが自由度は高い。
また、JavaScriptのクラス定義が面倒なのはJavaScriptの文法がクソ
なせいであって、プロトタイプベースのせいではない。
JSにクラス構文が入ったら、プロトタイプベー
スの特徴が失われてしまう!〔JS派による誤解〕
◆
糖衣構文が入っても、見た目が変わるだけで、プロトタイプベース
であることは変わらない。それよりも __proto__ の標準化が遅れて
いることを心配すべき(そのせいで JS はプロトタイプベースの利
点を活かせていない)。
copyright(c) 2013 kuwata-lab.com all rights reserved.
委譲と継承と
プロトタイプチェーン
Delegation, Inheritance, and Prototype Chain
copyright(c) 2013 kuwata-lab.com all rights reserved.
委譲
機能の一部 or 全部を、他のオブジェクトに任せ
ること(丸投げ!)
class	 Foo	 {
	 	 private	 $m1;
	 	 function	 __constructor()	 {
	 	 	 	 $this->other	 =	 new	 OtherObj();
	 	 }
	 	 function	 hello(arg)	 {
	 	 	 	 $this->other->hello(arg);
	 	 }
	 	 .... 丸投げ!
copyright(c) 2013 kuwata-lab.com all rights reserved.
委譲と継承はよく似ている
##	 継承は、メソッド探索を自動で行ってくれる
$this->isa->methodtbl->hello(...);
##	 委譲は、メソッド探索を自力で行っている
$this->other->hello(...);
◆
◆
委譲は、「継承の自力版」と見なせる
言語サポートはないかわりに、複数の移譲先が可能、変更も可能
継承は、「委譲の限定版」と見なせる
移譲先は1つだけで変更も不可だが、言語サポートがあるので便利
(注)独自の見解です
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプチェーン
##	 委譲と同様に、探索先を自分で設定可能
this.__proto__	 =	 new	 Foo();
##	 継承と同様に、自動的に探索してくれる
$this.hello();
$this.__proto__.hello();
$this.__proto__.__proto__.hello();
◆ プロトタイプチェーンは、委譲と継承の間の子
委譲の柔軟性と、継承の利便性を合わせ持つ
(注)独自の見解です
copyright(c) 2013 kuwata-lab.com all rights reserved.
継承では $this が変わらない
	 1:	 class	 Foo	 {
	 2:	 	 	 function	 hello()	 {	 ...	 }
	 3:	 	 	 function	 main()	 {
	 4:	 	 	 	 	 ...;	 $this->hello();	 ...;
	 5:	 	 	 }
	 6:	 }
	 7:	 class	 Bar	 extends	 Foo	 {
	 8:	 	 	 function	 hello()	 {...}	 	 //	 override
	 9:	 	 	 //	 main()	 はそのまま
10:	 }
11:	 $obj	 =	 new	 Bar();
12:	 $obj->main();
$this は Bar オブ
ジェクトのまま!
オーバーライドした
Bar#hello() が最終的に
呼び出される
難しい話なので、分から
なければ読み飛ばして!
copyright(c) 2013 kuwata-lab.com all rights reserved.
委譲では $this が変わる
	 1:	 class	 Foo	 {
	 2:	 	 	 function	 hello()	 {	 ...	 }
	 3:	 	 	 function	 main()	 {
	 4:	 	 	 	 	 ...;	 $this->hello();	 ...;	 }
	 5:	 }
	 6:	 class	 Bar	 extends	 Foo	 {
	 7:	 	 	 function	 hello()	 {	 ...	 }
	 8:	 	 	 function	 main()	 {
	 9:	 	 	 	 	 $this->foo->main();	 }
10:	 }
11:	 $obj	 =	 new	 Bar();
12:	 $obj->foo	 =	 new	 Foo();
13:	 $obj->main();
この $this は
Bar ではない!
せっかく Bar#hello() を
新しく定義したのに
呼び出されない!
(Decorator patternでありがち)
Foo オブジェクト
が $this になる!
難しい話なので、分から
なければ読み飛ばして!
copyright(c) 2013 kuwata-lab.com all rights reserved.
対策: $this を引数として渡す
class	 Foo	 {
	 	 function	 hello()	 {	 ...	 }
	 	 function	 main($_this=null)	 {
	 	 	 	 if	 ($_this	 ===	 null)	 $_this	 =	 $this;
	 	 	 	 ...;	 $_this->hello();	 ...;
	 	 }
}
class	 Bar	 {
	 	 var	 $foo	 =	 new	 Foo();
	 	 function	 hello()	 {	 ...	 }
	 	 function	 main()	 {
	 	 	 	 $this->foo->main($this);	 }	 }
こんな面倒なことを
全メソッドで行うの?
この用意をしてないクラス
は委譲先にできないの?
難しい話なので、分から
なければ読み飛ばして!
copyright(c) 2013 kuwata-lab.com all rights reserved.
プロトタイプチェーンでは this が変わらない
	 1:	 function	 Foo()	 {}
	 2:	 Foo.prototype.hello	 =	 function()	 {...};
	 3:	 Foo.prototype.main	 =	 function()	 {
	 4:	 	 	 ...;	 this.hello();	 ...;
	 5:	 };
	 6:
	 7:	 function	 Bar()	 {}
	 8:	 Bar.prototype.hello	 =	 function()	 {...};
	 9:	 
10:	 var	 obj	 =	 new	 Bar();
11:	 obj.__proto__	 =	 new	 Foo();
12:	 obj.main();
この this は Bar オ
ブジェクトのまま!
委譲と同じことしてるのに、
Bar#hello() が呼ばれる!
(Decorator pattern大勝利の気配!)
copyright(c) 2013 kuwata-lab.com all rights reserved.
比較表
継承
プロトタイプ
チェーン
委譲
言語サポート
利便性
委譲先数
委譲先
$this
あり あり なし
便利 便利 煩雑
1つだけ 1つだけ 複数指定可能
変更不可 変更可 変更可
変わらない 変わらない 変わる
- 継承をより柔軟にしたもの
- 委譲の煩雑さを解消したもの
copyright(c) 2013 kuwata-lab.com all rights reserved.
クラス設計
改善例
An Example to Improve Class Design
copyright(c) 2013 kuwata-lab.com all rights reserved.
間違ったクラス設計例
class	 受注先	 {
	 	 var	 $name;
	 	 var	 $addr;
	 	 function	 納期回答();
}
class	 発注先	 {
	 	 var	 $name;
	 	 var	 $addr;
	 	 function	 納期問合わせ();
}
「受注先かつ発注先」なら両方に登録が必要◆
実体は同じなのに一元管理されないため、名寄せが必要
自称DB設計上級者に
ありがちな間違い
copyright(c) 2013 kuwata-lab.com all rights reserved.
間違ったクラス設計例
class	 取引先	 {
	 	 var	 $name;
	 	 var	 $addr;
}
class	 受注先	 extends	 取引先	 {
	 	 function	 納期回答();
}
class	 発注先	 extends	 取引先	 {
	 	 function	 納期問合わせ();
}
class	 受発注先	 extends	 受注先,発注先	 {	 }
「受注先が発注先にJob Change!」を表せない◆
一度作ったオブジェクトのクラスは変更できないせい
自称Java上級者に
ありがちな間違い
ダイヤモンド継承!
copyright(c) 2013 kuwata-lab.com all rights reserved.
好ましいクラス設計例
class	 取引先	 {	 	 //	 Player
	 	 var	 $name;
	 	 var	 $addr;
	 	 var	 $受注先	 =	 new	 受注先();
	 	 var	 $発注先	 =	 new	 発注先();
}
class	 受注先	 {	 	 //	 Role
	 	 function	 納期回答();	 }
class	 発注先	 {	 	 //	 Role
	 	 function	 納期問合わせ();	 }
「Player」と「Role」とを分け、委譲を使う◆
「受注先かつ発注先」も「Job Change!」も自然に表現可能
でも、受注先や発注
先って、対応する取
引先オブジェクトが
必要だよね?
copyright(c) 2013 kuwata-lab.com all rights reserved.
より好ましいクラス設計例
class	 取引先	 {	 ...	 }
class	 Role	 {
	 	 var	 $player;
	 	 function	 __constructor($player)	 {
	 	 	 	 $this->player	 =	 $player;
	 	 }
}
class	 受注先	 extends	 Role	 {	 ...	 }
class	 発注先	 extends	 Role	 {	 ...	 }
「Role」が「Player」を保持する(さっきと逆)◆
Role には Player が必要だが、Player には Role は必須ではない
Role が Player を保持
(なぜなら Role には Player が必要だから)
copyright(c) 2013 kuwata-lab.com all rights reserved.
若干の問題点
//	 受注先である取引先
$player	 =	 new	 取引先('○ 商会');
$role	 	 	 =	 new	 受注先($player);
//	 受注先として扱う
echo	 $role->納期回答();
//	 取引先として扱う
echo	 $role->player->name;
echo	 $player->name;
Role と Player で使い方に差がある◆
Player の属性やメソッドに Role からアクセスするとき
Role からは、Player の属性へ
直接にはアクセスできない
copyright(c) 2013 kuwata-lab.com all rights reserved.
そこでプロトタイプベース!
class	 取引先	 {	 ...	 }
class	 Role	 {
	 	 function	 __constructor($player)	 {
	 	 	 	 $this->player	 =	 $player;
	 	 	 	 $this->__proto__	 =	 $player;
	 	 }
}
class	 受注先	 extends	 Role	 {	 ...	 }
class	 発注先	 extends	 Role	 {	 ...	 }
Role をあたかも Player のように扱える◆
Decorator Pattern も DCI もいらんかったんや!
仮に PHP でこれが
可能だとすると…
copyright(c) 2013 kuwata-lab.com all rights reserved.
そこでプロトタイプベース!
//	 受注先	 (Role)	 の役割をもった取引先	 (Player)	 は、
$player	 =	 new	 取引先('○ 商会');
$role	 	 	 =	 new	 受注先($player);
//	 Role	 としても	 Player	 としても扱える
echo	 $role->納期回答();
echo	 $role->name;
//	 複数の	 Role	 を重ねることさえ可能
$role	 =	 new	 発注先($role);	 	 //	 受注先兼発注先
Role をあたかも Player のように扱える◆
Decorator Pattern も DCI もいらんかったんや!
Role なのに、まるで
Player のように扱える!
Any Questions?
おしまい

Mais conteúdo relacionado

Mais procurados

Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Takuya Akiba
 

Mais procurados (20)

【入門編】 ”はじめてのKong” APIゲートウェイとService Meshについて学ぼう!
【入門編】 ”はじめてのKong” APIゲートウェイとService Meshについて学ぼう! 【入門編】 ”はじめてのKong” APIゲートウェイとService Meshについて学ぼう!
【入門編】 ”はじめてのKong” APIゲートウェイとService Meshについて学ぼう!
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみよう
 
OSvの概要と実装
OSvの概要と実装OSvの概要と実装
OSvの概要と実装
 
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
 
ZDD基礎
ZDD基礎ZDD基礎
ZDD基礎
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 
Kotlin/Native 「使ってみた」の一歩先へ
Kotlin/Native 「使ってみた」の一歩先へKotlin/Native 「使ってみた」の一歩先へ
Kotlin/Native 「使ってみた」の一歩先へ
 
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
 
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
 
ROS2勉強会 4章前半
ROS2勉強会 4章前半ROS2勉強会 4章前半
ROS2勉強会 4章前半
 
いまさら恥ずかしくてAsyncをawaitした
いまさら恥ずかしくてAsyncをawaitしたいまさら恥ずかしくてAsyncをawaitした
いまさら恥ずかしくてAsyncをawaitした
 
Rpn and forth 超入門
Rpn and forth 超入門Rpn and forth 超入門
Rpn and forth 超入門
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
Curso básico de Algoritmos com Python
Curso básico de Algoritmos com PythonCurso básico de Algoritmos com Python
Curso básico de Algoritmos com Python
 
2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画
 
RDBにおけるバリデーションをリレーショナルモデルから考える
RDBにおけるバリデーションをリレーショナルモデルから考えるRDBにおけるバリデーションをリレーショナルモデルから考える
RDBにおけるバリデーションをリレーショナルモデルから考える
 
競技プログラミング頻出アルゴリズム攻略
競技プログラミング頻出アルゴリズム攻略競技プログラミング頻出アルゴリズム攻略
競技プログラミング頻出アルゴリズム攻略
 
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
DSIRNLP #3 LZ4 の速さの秘密に迫ってみる
DSIRNLP #3 LZ4 の速さの秘密に迫ってみるDSIRNLP #3 LZ4 の速さの秘密に迫ってみる
DSIRNLP #3 LZ4 の速さの秘密に迫ってみる
 

Destaque

ドラえもんの世界をオブジェクト指向で
ドラえもんの世界をオブジェクト指向でドラえもんの世界をオブジェクト指向で
ドラえもんの世界をオブジェクト指向で
yaju88
 

Destaque (12)

ドラえもんの世界をオブジェクト指向で
ドラえもんの世界をオブジェクト指向でドラえもんの世界をオブジェクト指向で
ドラえもんの世界をオブジェクト指向で
 
Webエンジニアのサバイバル英会話
Webエンジニアのサバイバル英会話Webエンジニアのサバイバル英会話
Webエンジニアのサバイバル英会話
 
C#の書き方
C#の書き方C#の書き方
C#の書き方
 
Quick tour of PHP from inside
Quick tour of PHP from insideQuick tour of PHP from inside
Quick tour of PHP from inside
 
9_C言語入門 - 条件分岐について(switch case)
9_C言語入門 - 条件分岐について(switch case)9_C言語入門 - 条件分岐について(switch case)
9_C言語入門 - 条件分岐について(switch case)
 
UXデザイナー1年生の1年間
UXデザイナー1年生の1年間UXデザイナー1年生の1年間
UXデザイナー1年生の1年間
 
関数型言語とオブジェクト指向言語(序章)
関数型言語とオブジェクト指向言語(序章)関数型言語とオブジェクト指向言語(序章)
関数型言語とオブジェクト指向言語(序章)
 
Unityで覚えるC#
Unityで覚えるC#Unityで覚えるC#
Unityで覚えるC#
 
40分濃縮 PHP classの教室
40分濃縮 PHP classの教室40分濃縮 PHP classの教室
40分濃縮 PHP classの教室
 
UX / UIデザインって何?
UX / UIデザインって何?UX / UIデザインって何?
UX / UIデザインって何?
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!
 

Semelhante a PHPとJavaScriptにおけるオブジェクト指向を比較する

G*workshop sendai 20100424(v2)
G*workshop sendai 20100424(v2)G*workshop sendai 20100424(v2)
G*workshop sendai 20100424(v2)
Nobuhiro Sue
 
Prototypeベース in JavaScript
Prototypeベース in JavaScriptPrototypeベース in JavaScript
Prototypeベース in JavaScript
Ryo Maruyama
 
Phjosh(仮)プロジェクト
Phjosh(仮)プロジェクトPhjosh(仮)プロジェクト
Phjosh(仮)プロジェクト
Moriyoshi Koizumi
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
Hidekazu Ishikawa
 
Javascript勉強会資料1
Javascript勉強会資料1Javascript勉強会資料1
Javascript勉強会資料1
Kenji Kaneko
 

Semelhante a PHPとJavaScriptにおけるオブジェクト指向を比較する (20)

G*workshop sendai 20100424(v2)
G*workshop sendai 20100424(v2)G*workshop sendai 20100424(v2)
G*workshop sendai 20100424(v2)
 
PHP基礎勉強会
PHP基礎勉強会PHP基礎勉強会
PHP基礎勉強会
 
Prototypeベース in JavaScript
Prototypeベース in JavaScriptPrototypeベース in JavaScript
Prototypeベース in JavaScript
 
WordPress テーマ作成&PHP超入門
WordPress テーマ作成&PHP超入門WordPress テーマ作成&PHP超入門
WordPress テーマ作成&PHP超入門
 
Javascripでオブジェクト指向
Javascripでオブジェクト指向Javascripでオブジェクト指向
Javascripでオブジェクト指向
 
PHPコアから読み解くPHP5.5
PHPコアから読み解くPHP5.5PHPコアから読み解くPHP5.5
PHPコアから読み解くPHP5.5
 
Datomic&datalog紹介
Datomic&datalog紹介Datomic&datalog紹介
Datomic&datalog紹介
 
【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト
【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト
【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト
 
Lithium Labo #1
Lithium Labo #1Lithium Labo #1
Lithium Labo #1
 
Spock's world
Spock's worldSpock's world
Spock's world
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
Phjosh(仮)プロジェクト
Phjosh(仮)プロジェクトPhjosh(仮)プロジェクト
Phjosh(仮)プロジェクト
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
 
Javascript勉強会資料1
Javascript勉強会資料1Javascript勉強会資料1
Javascript勉強会資料1
 
クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介
 
Java オブジェクトの内部構造
Java オブジェクトの内部構造Java オブジェクトの内部構造
Java オブジェクトの内部構造
 
最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)
 
An Internal of LINQ to Objects
An Internal of LINQ to ObjectsAn Internal of LINQ to Objects
An Internal of LINQ to Objects
 
正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?
 
第5回勉強会
第5回勉強会第5回勉強会
第5回勉強会
 

Mais de kwatch

文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
kwatch
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"
kwatch
 
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
kwatch
 

Mais de kwatch (20)

How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
 
Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
 
なんでもID
なんでもIDなんでもID
なんでもID
 
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 
Pretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/MercurialPretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/Mercurial
 
Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -
 
文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"
 
Cより速いRubyプログラム
Cより速いRubyプログラムCより速いRubyプログラム
Cより速いRubyプログラム
 
Javaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジンJavaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジン
 
Underlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R MapperUnderlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R Mapper
 
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
 
Benchmarker - A Good Friend for Performance
Benchmarker - A Good Friend for PerformanceBenchmarker - A Good Friend for Performance
Benchmarker - A Good Friend for Performance
 

Último

Último (12)

LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 

PHPとJavaScriptにおけるオブジェクト指向を比較する

  • 1. copyright(c) 2013 kuwata-lab.com all rights reserved. PHPとJavaScriptにおける オブジェクト指向を比較する makoto kuwata <kwa@kuwata-lab.com> http://www.kuwata-lab.com/ 2013-09-14 (Sat) PHPカンファレンス2013 【更新履歴】 ・2013-09-17: 大幅に加筆修正
  • 2. copyright(c) 2013 kuwata-lab.com all rights reserved. 本発表について • PHPでのオブジェクト指向の仕組みを理解する • JavaScriptでの(同上) • Class BaseとPrototype Baseの違いを理解する • オブジェクト指向言語の基礎知識があること (クラス、インスタンス、メソッド、etc) • JavaScriptを書いた経験があること • 独自の解釈が登場!自分で考えて判断を! 【目的】 【前提】 【注意】
  • 3. copyright(c) 2013 kuwata-lab.com all rights reserved. オブジェクト指向機能の仕組み (PHP編) Internal Mechanism of OOP in PHP
  • 4. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } オブジェクト指向機能の肝であるメソッド呼び出しの仕組みを説明します。
  • 5. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } 変数はポインタであり、インスタンスオブジェクトを参照しています。
  • 6. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } インスタンスオブジェクトには、クラスオブジェクトへの隠しポインタがあります。
  • 7. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } クラスオブジェクトは、メソッド探索テーブルへのポインタを持っています。
  • 8. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } メソッド名をキーにしてメソッド関数を探し、もしあれば実行します。
  • 9. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } もしメソッド名が見つからなければ、親クラスを ります。
  • 10. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } そこでも同じように、メソッド探索テーブルを使ってメソッドを検索します。
  • 11. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } 最後にルートクラスでもメソッドが見つからなければ、実行時エラーとなります。
  • 12. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 function () { ..... } Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } このように、メソッドは呼び出し時に「探索」される点が、関数と決定的に違います。 オブジェクト指向の柔軟性はこれのおかげですが、関数より遅い原因でもあります。
  • 13. copyright(c) 2013 kuwata-lab.com all rights reserved. インスタンス変数とインスタンスメソッド クラス x: 15 y: 25 メソッド表 m4 m2 m3 Z: 456 function () { ..... } インスタンス変数はインスタン スのもの(共有されない) インスタンスメソッドは クラスのもの(共有される) メソッド関数 インスタンス x: 10 y: 20 x: 30 y: 40
  • 14. copyright(c) 2013 kuwata-lab.com all rights reserved. is-aポインタ 所属するクラスオブジェクトを指す隠しポインタ◆ つまりインスタンスは、「自分が何者かを知っている」 x: 10 インスタンス クラス 変数 y: 20 is-a ポインタは is-a 関係を表す
  • 15. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド探索テーブル メソッドテーブル m1 m2 m3 function () { echo "hello"; } function ($x) { return $x + 1; } クラス メソッド名 + メソッド関数へのポインタ◆ メソッド名をキーにして、メソッド関数が動的に検索される (注) (注)正確には「メソッドシグニチャ」(詳細は省略)
  • 16. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッドオーバーライドと parent 呼び出し 変数 インスタンス クラス クラス x: 10 y: 20 メソッド表 メソッド表 m4 m2 m3 m3 m1 m2 Z: 123 Z: 456 メソッド関数 function () { ..... } function () { ..... } 同じ名前で別の関数を 登録するのがオーバーライド 自クラスをスキップして 親クラスから探索するのが parent 呼び出し メソッド関数
  • 17. copyright(c) 2013 kuwata-lab.com all rights reserved. オブジェクト指向機能の仕組み (JavaScript編) Internal Mechanism of OOP in JavaScript
  • 18. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト JavaScript におけるメソッド呼び出しの仕組みを説明します。
  • 19. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 変数はオブジェクトを指しています。そこにプロパティがあるかを調べます。
  • 20. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 指定されたプロパティがなければ、別のオブジェクトをたどります。
  • 21. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 見つかったプロパティが関数であれば、メソッドとして実行できます。
  • 22. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 見つからなければ、さらに別のオブジェクトをたどって、
  • 23. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 同じようにプロパティを探します。
  • 24. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト 最後までたどっても見つからなかれば、(JSでは) undefined が返されます。
  • 25. copyright(c) 2013 kuwata-lab.com all rights reserved. メソッド呼び出し 変数 オブジェクト オブジェクト オブジェクト x: 10 y: 20 function () { ..... } m2: Z: 456 関数オブジェクト function () { ..... } m1: m2: 関数オブジェクト このように、JavaScriptの動作もPHPとよく似ています。ただし、クラスやメソッド 探索テーブルは存在せず、すべてオブジェクトで済ませているのが特徴です。
  • 26. copyright(c) 2013 kuwata-lab.com all rights reserved. __proto__ プロパティ プロパティが自分にないときに探しに行く先◆ is-a ポインタに相当するが、任意のオブジェクトを自分で指定可能 height: 15 オブジェクト変数 obj __proto__: height: 0 オブジェクト width: 0 __proto__: width: 30 color: 'red' obj.color == 'red' (注) (注)IE9 以前では利用不可
  • 27. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプチェーン プロパティが見つかるまで __proto__ をたどる◆ 最後までたどっても見つからなければ undefined を返す y: 20 オブジェクト __proto__: x: 10 オブジェクト y: 10 __proto__: x: 0 オブジェクト y: 0 __proto__: z: 0探してるのが 「y」ならこれ が使われる 「x」ならこれ が使われる 「z」ならここ まで探しにくる
  • 28. copyright(c) 2013 kuwata-lab.com all rights reserved. コンストラクタ function Foo(x) { this.x = x; } Foo.prototype.value = 100; Foo.prototype.hello = function() { ... }; prototype: 関数オブジェクト name: 'Foo' __proto__: 変数 Foo 関数オブ ジェクト value: 100 hello: __proto__: オブジェクト __proto__ と .prototype は 別であることに注意
  • 29. copyright(c) 2013 kuwata-lab.com all rights reserved. new 演算子 var obj = new Foo(123); obj.hello(); x: 123 オブジェクト __proto__: 変数 obj prototype: 関数オブジェクト name: 'Foo' __proto__: 変数 Foo 関数オブ ジェクト value: 100 hello: __proto__: オブジェクト 空オブジェクトを生成、 __proto__ を設定、 コンストラクタを適用
  • 30. copyright(c) 2013 kuwata-lab.com all rights reserved. __proto__ と prototype の違いがわかりません! Foo.__proto__ は、Foo という(関数)オブジェ クトのためのもの ◆ new で新規作成するオブジェクトには、何も関係しない Foo.prototype は、new で新規作成するオブジェ クトのためのもの ◆ Foo 関数自身のプロトタイプチェーンには、何も関係しない
  • 31. copyright(c) 2013 kuwata-lab.com all rights reserved. クラスベース (PHP) と プロトタイプベース (JS) Class Base v.s. Prototype Base
  • 32. copyright(c) 2013 kuwata-lab.com all rights reserved. 北の賢者曰く プロトタイプベースにいくつかの制約を加えたのが クラスベースである。 つまり、クラスベースはプロトタイプベースのサブ セットである。 “ ” http://sumim.no-ip.com/wiki/493 (「超約」してるので原文を確認のこと) by sumim
  • 33. copyright(c) 2013 kuwata-lab.com all rights reserved. is-a ポインタ v.s. __proto__ プロパティ $obj->isa = new Other(); // できない is-a ポインタは、プロブラマが変更できない◆ そもそもプログラマには見えない obj.__proto__ = new Other(); // できる! __proto__ プロパティは、自由に変更できる◆ 任意のオブジェクトを設定できる
  • 34. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプベース + 制約 = クラスベース クラスベース (PHP) プロトタイプベース (JS) 探索 ポインタ ポイント対象 ポインタ先 クラスチェーン プロトタイプチェーン is-a ポインタ __proto__ プロパティ クラスオブジェクトのみ 任意のオブジェクト 変更不可 変更可能 制約がない制約がある! “プロトタイプベースにいくつかの制約を 加えたのがクラスベースである。”
  • 35. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプベース ⊃ クラスベース プロトタイプベース クラスベース 両者は、排他関係ではなく包含関係◆ 制約がある分、クラスベースのほうが「狭い」 “クラスベースはプロトタイプベースの サブセットである。”
  • 36. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプベースの 応用パターン Advanced Pattern of Prorotype Base
  • 37. copyright(c) 2013 kuwata-lab.com all rights reserved. 設定ファイル用オブジェクト default (共通) 共通する設定を一元管理◆ 開発用と本番用は差分だけを管理 development (開発用) __proto__: user: "your-name" production (本番用) __proto__: user: "wpadmin" pass: "bh#un?j9" __proto__: host: "localhost" port: 3306 user: "" pass: "" db: "wordpress"
  • 38. copyright(c) 2013 kuwata-lab.com all rights reserved. 追記型オブジェクト 一度公開したオブジェクトは一切変更しない◆ 変更するかわりに、差分だけのオブジェクトを作り (注)、その __proto__ にもとのオブジェクトを設定。 (注) 値の削除は、undefined で表現する。 __proto__: color: "red" version: 3 __proto__: height: 125 version: 4 __proto__: width: 55 version: 2 __proto__: height: 120 width: 50 color: "pink" version: 1 created: "09/14"
  • 39. copyright(c) 2013 kuwata-lab.com all rights reserved. DCI (Data, Context, Interaction), Decorator Pattern __proto__: name: "○×社" addr: "東京" phone: "03-..." created: "09/14" __proto__: 納期問合せ() 発注処理() 発注先 (Role) __proto__: 納期回答() 受注処理() 受注先 (Role) 取引先 (Player) インスタンス単位での拡張や追加がとても自然◆ 「差分プログラミング」がクラス単位ではなくインスタンス単位に 「受注先」と して機能する 「取引先」 「受注先」かつ 「発注先」であ る「取引先」 (あとで詳しくやります…)
  • 40. copyright(c) 2013 kuwata-lab.com all rights reserved. よくある誤解 プロトタイプベースは面倒、クラスベースのほ うが簡単で便利!〔PHP派による誤解〕 ◆ 制約がない分、プロトタイプベースのほうが自由度は高い。 また、JavaScriptのクラス定義が面倒なのはJavaScriptの文法がクソ なせいであって、プロトタイプベースのせいではない。 JSにクラス構文が入ったら、プロトタイプベー スの特徴が失われてしまう!〔JS派による誤解〕 ◆ 糖衣構文が入っても、見た目が変わるだけで、プロトタイプベース であることは変わらない。それよりも __proto__ の標準化が遅れて いることを心配すべき(そのせいで JS はプロトタイプベースの利 点を活かせていない)。
  • 41. copyright(c) 2013 kuwata-lab.com all rights reserved. 委譲と継承と プロトタイプチェーン Delegation, Inheritance, and Prototype Chain
  • 42. copyright(c) 2013 kuwata-lab.com all rights reserved. 委譲 機能の一部 or 全部を、他のオブジェクトに任せ ること(丸投げ!) class Foo { private $m1; function __constructor() { $this->other = new OtherObj(); } function hello(arg) { $this->other->hello(arg); } .... 丸投げ!
  • 43. copyright(c) 2013 kuwata-lab.com all rights reserved. 委譲と継承はよく似ている ## 継承は、メソッド探索を自動で行ってくれる $this->isa->methodtbl->hello(...); ## 委譲は、メソッド探索を自力で行っている $this->other->hello(...); ◆ ◆ 委譲は、「継承の自力版」と見なせる 言語サポートはないかわりに、複数の移譲先が可能、変更も可能 継承は、「委譲の限定版」と見なせる 移譲先は1つだけで変更も不可だが、言語サポートがあるので便利 (注)独自の見解です
  • 44. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプチェーン ## 委譲と同様に、探索先を自分で設定可能 this.__proto__ = new Foo(); ## 継承と同様に、自動的に探索してくれる $this.hello(); $this.__proto__.hello(); $this.__proto__.__proto__.hello(); ◆ プロトタイプチェーンは、委譲と継承の間の子 委譲の柔軟性と、継承の利便性を合わせ持つ (注)独自の見解です
  • 45. copyright(c) 2013 kuwata-lab.com all rights reserved. 継承では $this が変わらない 1: class Foo { 2: function hello() { ... } 3: function main() { 4: ...; $this->hello(); ...; 5: } 6: } 7: class Bar extends Foo { 8: function hello() {...} // override 9: // main() はそのまま 10: } 11: $obj = new Bar(); 12: $obj->main(); $this は Bar オブ ジェクトのまま! オーバーライドした Bar#hello() が最終的に 呼び出される 難しい話なので、分から なければ読み飛ばして!
  • 46. copyright(c) 2013 kuwata-lab.com all rights reserved. 委譲では $this が変わる 1: class Foo { 2: function hello() { ... } 3: function main() { 4: ...; $this->hello(); ...; } 5: } 6: class Bar extends Foo { 7: function hello() { ... } 8: function main() { 9: $this->foo->main(); } 10: } 11: $obj = new Bar(); 12: $obj->foo = new Foo(); 13: $obj->main(); この $this は Bar ではない! せっかく Bar#hello() を 新しく定義したのに 呼び出されない! (Decorator patternでありがち) Foo オブジェクト が $this になる! 難しい話なので、分から なければ読み飛ばして!
  • 47. copyright(c) 2013 kuwata-lab.com all rights reserved. 対策: $this を引数として渡す class Foo { function hello() { ... } function main($_this=null) { if ($_this === null) $_this = $this; ...; $_this->hello(); ...; } } class Bar { var $foo = new Foo(); function hello() { ... } function main() { $this->foo->main($this); } } こんな面倒なことを 全メソッドで行うの? この用意をしてないクラス は委譲先にできないの? 難しい話なので、分から なければ読み飛ばして!
  • 48. copyright(c) 2013 kuwata-lab.com all rights reserved. プロトタイプチェーンでは this が変わらない 1: function Foo() {} 2: Foo.prototype.hello = function() {...}; 3: Foo.prototype.main = function() { 4: ...; this.hello(); ...; 5: }; 6: 7: function Bar() {} 8: Bar.prototype.hello = function() {...}; 9: 10: var obj = new Bar(); 11: obj.__proto__ = new Foo(); 12: obj.main(); この this は Bar オ ブジェクトのまま! 委譲と同じことしてるのに、 Bar#hello() が呼ばれる! (Decorator pattern大勝利の気配!)
  • 49. copyright(c) 2013 kuwata-lab.com all rights reserved. 比較表 継承 プロトタイプ チェーン 委譲 言語サポート 利便性 委譲先数 委譲先 $this あり あり なし 便利 便利 煩雑 1つだけ 1つだけ 複数指定可能 変更不可 変更可 変更可 変わらない 変わらない 変わる - 継承をより柔軟にしたもの - 委譲の煩雑さを解消したもの
  • 50. copyright(c) 2013 kuwata-lab.com all rights reserved. クラス設計 改善例 An Example to Improve Class Design
  • 51. copyright(c) 2013 kuwata-lab.com all rights reserved. 間違ったクラス設計例 class 受注先 { var $name; var $addr; function 納期回答(); } class 発注先 { var $name; var $addr; function 納期問合わせ(); } 「受注先かつ発注先」なら両方に登録が必要◆ 実体は同じなのに一元管理されないため、名寄せが必要 自称DB設計上級者に ありがちな間違い
  • 52. copyright(c) 2013 kuwata-lab.com all rights reserved. 間違ったクラス設計例 class 取引先 { var $name; var $addr; } class 受注先 extends 取引先 { function 納期回答(); } class 発注先 extends 取引先 { function 納期問合わせ(); } class 受発注先 extends 受注先,発注先 { } 「受注先が発注先にJob Change!」を表せない◆ 一度作ったオブジェクトのクラスは変更できないせい 自称Java上級者に ありがちな間違い ダイヤモンド継承!
  • 53. copyright(c) 2013 kuwata-lab.com all rights reserved. 好ましいクラス設計例 class 取引先 { // Player var $name; var $addr; var $受注先 = new 受注先(); var $発注先 = new 発注先(); } class 受注先 { // Role function 納期回答(); } class 発注先 { // Role function 納期問合わせ(); } 「Player」と「Role」とを分け、委譲を使う◆ 「受注先かつ発注先」も「Job Change!」も自然に表現可能 でも、受注先や発注 先って、対応する取 引先オブジェクトが 必要だよね?
  • 54. copyright(c) 2013 kuwata-lab.com all rights reserved. より好ましいクラス設計例 class 取引先 { ... } class Role { var $player; function __constructor($player) { $this->player = $player; } } class 受注先 extends Role { ... } class 発注先 extends Role { ... } 「Role」が「Player」を保持する(さっきと逆)◆ Role には Player が必要だが、Player には Role は必須ではない Role が Player を保持 (なぜなら Role には Player が必要だから)
  • 55. copyright(c) 2013 kuwata-lab.com all rights reserved. 若干の問題点 // 受注先である取引先 $player = new 取引先('○ 商会'); $role = new 受注先($player); // 受注先として扱う echo $role->納期回答(); // 取引先として扱う echo $role->player->name; echo $player->name; Role と Player で使い方に差がある◆ Player の属性やメソッドに Role からアクセスするとき Role からは、Player の属性へ 直接にはアクセスできない
  • 56. copyright(c) 2013 kuwata-lab.com all rights reserved. そこでプロトタイプベース! class 取引先 { ... } class Role { function __constructor($player) { $this->player = $player; $this->__proto__ = $player; } } class 受注先 extends Role { ... } class 発注先 extends Role { ... } Role をあたかも Player のように扱える◆ Decorator Pattern も DCI もいらんかったんや! 仮に PHP でこれが 可能だとすると…
  • 57. copyright(c) 2013 kuwata-lab.com all rights reserved. そこでプロトタイプベース! // 受注先 (Role) の役割をもった取引先 (Player) は、 $player = new 取引先('○ 商会'); $role = new 受注先($player); // Role としても Player としても扱える echo $role->納期回答(); echo $role->name; // 複数の Role を重ねることさえ可能 $role = new 発注先($role); // 受注先兼発注先 Role をあたかも Player のように扱える◆ Decorator Pattern も DCI もいらんかったんや! Role なのに、まるで Player のように扱える!