SlideShare a Scribd company logo
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?
おしまい

More Related Content

What's hot (20)

PPTX
PubMedBERT: 生物医学NLPのための事前学習
Naoto Usuyama
 
PDF
KVM環境におけるネットワーク速度ベンチマーク
VirtualTech Japan Inc.
 
PPTX
押さえておきたい、PostgreSQL 13 の新機能!! (PostgreSQL Conference Japan 2020講演資料)
NTT DATA Technology & Innovation
 
PPTX
adversarial training.pptx
ssuserc45ddf
 
PDF
PCE 〜MPLSネットワークのSDN化を本気で実現する"唯一の"方法〜
Takuya Miyasaka
 
PDF
20190625 OpenACC 講習会 第3部
NVIDIA Japan
 
PDF
Gitの便利ワザ
ktateish
 
PDF
Elasticsearchを使うときの注意点 公開用スライド
崇介 藤井
 
PPTX
PHPのテスト名を日本語にした話
Norifumi Kawamoto
 
PDF
ChatGPT、 何が「できる」「みえる」ようになってきたのか!
Jingun Jung
 
PDF
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
TetsuroMatsumura
 
PPTX
乱数調整概説
Blastoise_X
 
PPTX
php-src の歩き方
do_aki
 
PPTX
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
DongMin Choi
 
PPTX
強化学習アルゴリズムPPOの解説と実験
克海 納谷
 
PDF
PyData.Tokyo Meetup #21 講演資料「Optuna ハイパーパラメータ最適化フレームワーク」太田 健
Preferred Networks
 
PDF
いまさら聞けない!CUDA高速化入門
Fixstars Corporation
 
PDF
PFN Summer Internship 2021 / Kohei Shinohara: Charge Transfer Modeling in Neu...
Preferred Networks
 
PDF
CRF を使った Web 本文抽出
Shuyo Nakatani
 
PDF
SSD: Single Shot MultiBox Detector (ECCV2016)
Takanori Ogata
 
PubMedBERT: 生物医学NLPのための事前学習
Naoto Usuyama
 
KVM環境におけるネットワーク速度ベンチマーク
VirtualTech Japan Inc.
 
押さえておきたい、PostgreSQL 13 の新機能!! (PostgreSQL Conference Japan 2020講演資料)
NTT DATA Technology & Innovation
 
adversarial training.pptx
ssuserc45ddf
 
PCE 〜MPLSネットワークのSDN化を本気で実現する"唯一の"方法〜
Takuya Miyasaka
 
20190625 OpenACC 講習会 第3部
NVIDIA Japan
 
Gitの便利ワザ
ktateish
 
Elasticsearchを使うときの注意点 公開用スライド
崇介 藤井
 
PHPのテスト名を日本語にした話
Norifumi Kawamoto
 
ChatGPT、 何が「できる」「みえる」ようになってきたのか!
Jingun Jung
 
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
TetsuroMatsumura
 
乱数調整概説
Blastoise_X
 
php-src の歩き方
do_aki
 
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
DongMin Choi
 
強化学習アルゴリズムPPOの解説と実験
克海 納谷
 
PyData.Tokyo Meetup #21 講演資料「Optuna ハイパーパラメータ最適化フレームワーク」太田 健
Preferred Networks
 
いまさら聞けない!CUDA高速化入門
Fixstars Corporation
 
PFN Summer Internship 2021 / Kohei Shinohara: Charge Transfer Modeling in Neu...
Preferred Networks
 
CRF を使った Web 本文抽出
Shuyo Nakatani
 
SSD: Single Shot MultiBox Detector (ECCV2016)
Takanori Ogata
 

Viewers also liked (12)

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

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

PPT
G*workshop sendai 20100424(v2)
Nobuhiro Sue
 
PPTX
PHP基礎勉強会
Yuji Otani
 
PDF
Prototypeベース in JavaScript
Ryo Maruyama
 
PDF
WordPress テーマ作成&PHP超入門
Michinari Odajima
 
PDF
Javascripでオブジェクト指向
1000 VICKY
 
PDF
PHPコアから読み解くPHP5.5
Yahoo!デベロッパーネットワーク
 
PDF
【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト
アシアル株式会社
 
PDF
Lithium Labo #1
Yusuke Ando
 
PDF
Spock's world
Takuma Watabiki
 
PDF
ATN No.2 Scala事始め
AdvancedTechNight
 
PDF
Phjosh(仮)プロジェクト
Moriyoshi Koizumi
 
PDF
脱コピペ!デザイナーにもわかるPHPとWP_Query
Hidekazu Ishikawa
 
PPTX
Javascript勉強会資料1
Kenji Kaneko
 
PDF
クライアントサイドjavascript簡単紹介
しくみ製作所
 
PDF
Java オブジェクトの内部構造
Taku Miyakawa
 
PDF
最新PHP事情 (2000年7月22日,PHPカンファレンス)
Rui Hirokawa
 
PDF
An Internal of LINQ to Objects
Yoshifumi Kawai
 
PDF
正規表現リテラルは本当に必要なのか?
kwatch
 
PPT
第5回勉強会
Mugen Fujii
 
G*workshop sendai 20100424(v2)
Nobuhiro Sue
 
PHP基礎勉強会
Yuji Otani
 
Prototypeベース in JavaScript
Ryo Maruyama
 
WordPress テーマ作成&PHP超入門
Michinari Odajima
 
Javascripでオブジェクト指向
1000 VICKY
 
PHPコアから読み解くPHP5.5
Yahoo!デベロッパーネットワーク
 
【アシアル塾】PHPオブジェクト指向再入門・第一回クラスとオブジェクト
アシアル株式会社
 
Lithium Labo #1
Yusuke Ando
 
Spock's world
Takuma Watabiki
 
ATN No.2 Scala事始め
AdvancedTechNight
 
Phjosh(仮)プロジェクト
Moriyoshi Koizumi
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
Hidekazu Ishikawa
 
Javascript勉強会資料1
Kenji Kaneko
 
クライアントサイドjavascript簡単紹介
しくみ製作所
 
Java オブジェクトの内部構造
Taku Miyakawa
 
最新PHP事情 (2000年7月22日,PHPカンファレンス)
Rui Hirokawa
 
An Internal of LINQ to Objects
Yoshifumi Kawai
 
正規表現リテラルは本当に必要なのか?
kwatch
 
第5回勉強会
Mugen Fujii
 
Ad

More from kwatch (20)

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

Recently uploaded (8)

PDF
20250711_日本IBM ミドルウエア・ユーザー研究会(JIMUC)総会_中村会長資料.pdf
ChikakoInami1
 
PDF
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
PDF
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
PDF
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
PDF
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
PDF
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
PDF
PostgreSQL18新機能紹介(db tech showcase 2025 発表資料)
NTT DATA Technology & Innovation
 
PDF
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
20250711_日本IBM ミドルウエア・ユーザー研究会(JIMUC)総会_中村会長資料.pdf
ChikakoInami1
 
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
PostgreSQL18新機能紹介(db tech showcase 2025 発表資料)
NTT DATA Technology & Innovation
 
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 

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

  • 1. copyright(c) 2013 kuwata-lab.com all rights reserved. PHPとJavaScriptにおける オブジェクト指向を比較する makoto kuwata <[email protected]> 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 のように扱える!