clj / protocol
clojure 协议的 PHP 版本
1.0.0
2012-05-30 16:15 UTC
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2024-09-28 12:15:54 UTC
README
#PHP 的 Clojure 协议
##什么是协议?
有关更多信息,请参阅 Details.md 文件
##创建协议
-
创建一个接口,包含你想要协议实现的函数。接口中每个函数的第一个参数必须是调用对象。因此,创建你的接口如下
interface ILookup { public function get($context, $key, $default = null); public function exists($context, $key); }
而不是这样
interface ILookup { public function get($key, $default = null); public function exists($context, $key); }
-
创建实现接口的协议
class Lookup extends \Clj\AProtocol { public function get($object, $key, $default = null) { return $this->__getObject__($object)->get($object, $key, $default); } public function exists($object, $key) { return $this->__getObject__($object)->exists($object, $key); } }
__getObject__ 方法找到对象的类型,并返回协议的具体实现
-
创建协议的具体实现(在我的代码中,我将实现类型名称的前缀设置为 P,例如 PNull 表示 null 或 PDateTime 表示 DateTime 对象)
class PArray extends \Clj\AProtocolInstance implements ILookup //Lookup for arrays { public function get($context, $key, $default = null) { if (isset($context[$key]) || (array_key_exists($key, $context))) { return $context[$key]; } return $default; } public function exists($context, $key) { return (isset($context[$key]) || (array_key_exists($key, $context))); } } class PNull extends \Clj\AProtocolInstance implements ILookup //Lookup for null { public function get($context, $key, $default = null) { return $default; } public function exists($context, $key) { return false; } }
##使用协议管理器
使用 Protocol manager 类创建和扩展协议。要添加协议,请传递协议对象
$lookup = new Lookup();
$protocol_manager->add($lookup);
要向协议添加类型,可以使用 extendType 或 extendProtocol 方法
//Extends a type to an array of protocols
$protocol_manager->extendType(\Clj\IProtocol::PROTOCOL_NULL, array('ILookup' => new PNull()));
//Extends the protocol to an array of types
$protocol_manager->extendProtocol('ILookup', array(\Clj\IProtocol::PROTOCOL_NULL => new PNull(),
\Clj\IProtocol::PROTOCOL_ARRAY => new PArray()));
要检索扩展的协议,可以使用 getProtocol 或 getProtocolReference。以下是如何使用它们的示例
$lookup = new Lookup();
$protocol_manager->add($lookup);
$protocol_manager->extendType(\Clj\IProtocol::PROTOCOL_NULL, array('ILookup' => new PNull()));
//Gets the lookup protocol that only works for null types
$extended_lookup = $protocol_manager->getProtocol('ILookup');
$lookup_reference = $protocol_manager->getProtocolReference('ILookup');
$protocol_manager->extendType(\Clj\IProtocol::PROTOCOL_ARRAY, array('ILookup' => new PArray()));
$extended_lookup->get(null, 'foo', 'bar'); //Returns 'bar'
$extended_lookup->get(array('foo' => 'bar'), 'foo', 'bar'); //Throws excpetion
$lookup_reference->getRef()->get(null, 'foo', 'bar'); //Returns 'bar'
$lookup_reference->getRef()->get(array('foo' => 'BAZ'), 'foo', 'bar'); //Returns 'BAZ'
在示例中,getProtocol 返回在调用时存在的查找协议(仅针对 null 类型进行了扩展)。在之后对协议进行的任何扩展(将查找协议扩展到数组)都不会添加到 $extended_lookup
中。
相比之下,getProtocolReference 返回一个类似于 $a =& $b
的协议引用。但这个引用是只读的,并且通过 getRef 方法访问。这允许访问协议的所有扩展,而不仅仅是创建引用时存在的扩展。