#!/usr/local/bin/php <?php class AttrClass { private $attr_reader = array(); private $attr_writer = array(); private $attr = array(); protected function attr_accessor($attributes) { $add = $this->_my_flip($attributes); $this->attr_reader = array_merge($this->attr_reader, $add); $this->attr_writer = array_merge($this->attr_writer, $add); } protected function attr_reader($attributes) { $add = $this->_my_flip($attributes); $this->attr_reader = array_merge($this->attr_reader, $add); } protected function attr_writer($attributes) { $add = $this->_my_flip($attributes); $this->attr_writer = array_merge($this->attr_writer, $add); } private function _my_flip($mixed) { if (! is_array($mixed)) { $mixed = array($mixed); } return array_flip($mixed); } private function __set($name, $value) { if (array_key_exists($name, $this->attr_writer)) { $this->attr[$name] = $value; } else { throw new Exception("$name is undefined setter method"); } } private function __get($name) { if (array_key_exists($name, $this->attr_reader)) { return $this->attr[$name]; } else { throw new Exception("$name is undefined getter method"); } } } class Klass extends AttrClass { function __construct($foo, $bar, $baz) { $this->attr_accessor(array('foo', 'bar', 'baz')); $this->foo = $foo; $this->bar = $bar; $this->baz = $baz; } } $kls = new Klass('FOO', 'BAR', 'BAZ'); echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->bar = 'バー'; $kls->baz = 'バズ'; echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->hoge = 'HOGE'; ?>メソッド名はrubyのぱくり。
FOO BAR BAZ FOO バー バズ Fatal error: Uncaught exception 'Exception' with message 'hoge is undefined setter method' ...ここまではOK。
protected function attr_reader_user_func($attribute, $class, $func) { $this->attr_reader[$attribute] = array($class, $func); } protected function attr_writer_user_func($attribute, $class, $func) { $this->attr_writer[$attribute] = array($class, $func); } ... private function __set($name, $value) { if (array_key_exists($name, $this->attr_writer)) { if (is_callable($this->attr_writer[$name])) { call_user_func($this->attr_writer[$name], $value); } else { $this->attr[$name] = $value; } } else { throw new Exception("$name is undefined setter method"); } } private function __get($name) { if (array_key_exists($name, $this->attr_reader)) { if (is_callable($this->attr_reader[$name])) { return call_user_func($this->attr_reader[$name]); } else { return $this->attr[$name]; } } else { throw new Exception("$name is undefined getter method"); } }
class Klass extends AttrClass { function __construct($foo, $bar, $baz) { $this->attr_accessor(array('foo', 'bar', 'baz')); $this->attr_writer_user_func('foo', $this, 'set_foo'); $this->foo = $foo; $this->bar = $bar; $this->baz = $baz; } protected function set_foo($value) { $this->foo = strtolower($value) . '!!'; } } $kls = new Klass('FOO', 'BAR', 'BAZ'); echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->bar = 'バー'; $kls->baz = 'バズ'; echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->hoge = 'HOGE';
foo!! BAR BAZ foo!! バー バズ Fatal error: Uncaught exception 'Exception' with message 'hoge is undefined setter method' ...成功!!!
$kls = new Klass('FOO', 'BAR', 'BAZ'); echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->bar = 'バー'; $kls->baz = 'バズ'; echo $kls->foo . PHP_EOL; echo $kls->bar . PHP_EOL; echo $kls->baz . PHP_EOL; $kls->foo = 'FOO2'; ←ここを追加 echo $kls->foo . PHP_EOL; ←ここを追加 $kls->hoge = 'HOGE';追加した部分に関しては
foo!! BAR BAZ foo!! バー バズ FOO2 ←あーあ・・・ Fatal error: Uncaught exception 'Exception' with message 'hoge is undefined setter method' ...となってしまった。
1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。
$ ruby -e "(1..100).map {|i| case true when i%3==0 && i%5==0 then 'FizzBuzz' when i%3==0 then 'Fizz' when i%5==0 then 'Buzz' else i end}.each {|v| print v, ' '}; puts" 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
抽象化は私たちが作業する時間を節約してはくれるが、私たちが学ぶ時間までは節約してくれないのだ。
この4.8節が激しく気になる・・。ボトムアップデザインはプログラムを読み易くする.この種の抽象化のインスタンスは,読む人に汎用オペレータを理解するよう要求する.
機能的抽象化のインスタンスは,読む人に特殊目的のサブルーチンを理解するよう要求する
「でもあんたのユーティリティを全部理解しないことには,プログラムが読めなくなるじゃないか.」
そういった言葉は大抵誤りだ.なぜかについては,第4.8節を参照