php Collection类的设计
用。net开发已经很多年了,最近接触到php,发现php也很好玩。不过发现它里面没有集合Collection类,只有数组,并且数组很强。这里我用数组来包装成一个集合Collection,代码如下:
class Collection{ private $_members = array (); public function addItem( $obj , $key =null) { if ( $key ) { if (isset( $this ->_members[ $key ])) { throw new exception( "Key \"$key\" already in use!" ); } else { $this ->_members[ $key ]= $obj ; } } else { $this ->_members[]= $obj ; } } public function removeItem( $key ) { if (isset( $this ->_members[ $key ])) { unset( $this ->_members[ $key ]); } else { throw new exception( "Invalid Key \"$key\"!" ); } } public function getItem( $key ) { if (isset( $this ->_members[ $key ])) { return $this ->_members[ $key ]; } else { throw new exception( "Invalid Key \"$key\"!" ); } } public function Keys() { return array_keys ( $this ->_members); } public function legth() { return sizeof( $this ->_members); } public function exists( $key ) { return (isset( $this ->_members[ $key ])); } } |
现在我们来测试一下这个集合是否好用。
我们首先建立一个集合元素类Course:
class Course { private $_id ; private $_courseCode ; private $_name ; public function __construct( $id , $courseCode , $name ) { $this ->_id= $id ; $this ->_courseCode= $courseCode ; $this ->_name= $name ; } public function getName() { return $this ->_name; } public function getID() { return $this ->_id; } public function getCourseCode() { return $this ->_courseCode; } public function __toString() { return $this ->_name; } } |
测试代码如下:
courses->addItem(new Course(1, "001", "语文"),1);
obj=obj;
我想这个集合类应该可以满足我们平日开发的需求了吧。
可是我们现在。net里面有个对象延迟加载,举个例子来说吧,假如现在有Student这个对象,它应该有很多Course,但是我们希望在访问Course之前Course是不会加载的。也就是说在实例化Student的时候Course个数为0,当我们需要Course的时候它才真正从数据库读取相应数据。就是需要我们把Collection做成惰性实例化。
修改后的Collection代码如下:
class Collection { private $_members = array(); //collection members private $_onload; //holder for callback function private $_isLoaded = false; //flag that indicates whether the callback //has been invoked public function addItem($obj, $key = null) { $this->_checkCallback(); //_checkCallback is defined a little later if($key) { if(isset($this->_members[$key])) { throw new KeyInUseException("Key \"$key\" already in use!"); } else { $this->_members[$key] = $obj; } } else { $this->_members[] = $obj; } } public function removeItem($key) { $this->_checkCallback(); if(isset($this->_members[$key])) { unset($this->_members[$key]); } else { throw new KeyInvalidException("Invalid key \"$key\"!"); } } public function getItem($key) { $this->_checkCallback(); if(isset($this->_members[$key])) { return $this->_members[$key]; } else { throw new KeyInvalidException("Invalid key \"$key\"!"); } } public function keys() { $this->_checkCallback(); return array_keys($this->_members); } public function length() { $this->_checkCallback(); return sizeof($this->_members); } public function exists($key) { $this->_checkCallback(); return (isset($this->_members[$key])); } /** * Use this method to define a function to be * invoked prior to accessing the collection. * The function should take a collection as a * its sole parameter. */ public function setLoadCallback($functionName, $objOrClass = null) { if($objOrClass) { $callback = array($objOrClass, $functionName); } else { $callback = $functionName; } //make sure the function/method is valid if(!is_callable($callback, false, $callableName)) { throw new Exception("$callableName is not callable " . "as a parameter to onload"); return false; } $this->_onload = $callback; } /** * Check to see if a callback has been defined and if so, * whether or not it has already been called. If not, * invoke the callback function. */ private function _checkCallback() { if(isset($this->_onload) && !$this->_isLoaded) { $this->_isLoaded = true; call_user_func($this->_onload, $this); } } }
所需的Student如下:
class CourseCollection extends Collection { public function addItem(Course $obj , $key =null) { parent::addItem( $obj , $key ); } } class Student{ private $_id ; private $_name ; public $course ; public function __construct( $id , $name ) { $this ->_id= $id ; $this ->_name= $name ; $this ->course= new CourseCollection(); $this ->course->setLoadCallback( 'loadCourses' , $this ); } public function getName() { return $this ->_name; } public function getID() { return $this ->_id; } public function __toString() { return $this ->_name; } public function loadCourses(Collection $col ) { $col ->addItem( new Course(1, "001" , "语文" ),1); $col ->addItem( new Course(2, "002" , "数学" ),2); } } |
调用代码如下:
student->getName();
print $student->course->getItem(1);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构