PHP面向对象的一些坑爹技巧

最近在肝PHP和Mysql

以我学了四天PHP的感觉来看

PHP的类如果不是考虑前后端彻底分离的话,用class来封装整个网页的Page用来重复利用还是不错的

然后在学习面向对象的时候有些坑爹(高深)的操作让我有些苦恼

1.迭代属性

<?php
	class myClass
	{
		public $a="xiao";
		public $b="yu";
		public $c="yu";
	}
	$x=new myClass;
	foreach ($x as $key )
	{
		echo $key."<br />";
	}
	echo "<br />";
?>

上面这段代码还是很简单的,就是用foreach输出类中的所有属性,然后开始玄学,迭代器……

2.迭代器

为什么要用迭代器呢,如果我们的迭代行为很复杂,用迭代器是不错的操作

然后重点来了迭代器(iterator)需要IteratorAggregate接口,getIterator(返回该迭代器实例)

生命一个类有迭代器接口的方法:

class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数

扫描二维码关注公众号,回复: 4205009 查看本文章

有哪些函数是需要的呢,如下(不需要析构函数)

	class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数
	{
		private $obj;
		private $count;
		private $currentIndex;
		//构造函数
		function __construct($obj)
		{
			$this->obj=$obj;
			$this->count=count($this->obj->data);
		}
		//重置内部数据指针
		function rewind()
		{
			$this->currentIndex=0;
		}
		//判断数据指针当前位置是否还存在更多数据
		function vaild()
		{
			return $this->currentIndex<$this->count; //true即为vaild
		}
		//返回数据指针值
		function key()
		{
			return $this->currentIndex;
		}
		//返回当前数据指针指向的数据
		function current()
		{
			return $this->obj->data[$this->currentIndex];
		}
		//向后移动数据指针1step
		function next()
		{
			$this->currentIndex++;
		}
	}

其实就是要把foreach的操作封装在类里面来应付各种各样的情况,乍一看比较多此一举,但是实际应用还是有价值的,不同的迭代方式我们用这些操作基本都可以搞定

这只是迭代器,我们还需要迭代器的接口IteratorAggregate,我们上面用的data就是接口里的变量,通过这个接口把需要迭代的变量传给迭代器运作(通过getIterator)

class Object implements IteratorAggregate
	{
		public $data=array();
		function __construct($in)
		{
			$this->data=$in;
		}
		function getIterator()
		{
			return new ObjectIterator($this);
		}
	}

分解开来慢慢分析其实还可以,就是把变量传进data,在把变量的指针传给迭代器,从而进行运作

给个例子

<?php
	class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数
	{
		private $obj;
		private $count;
		private $currentIndex;
		//构造函数
		function __construct($obj)
		{
			$this->obj=$obj;
			$this->count=count($this->obj->data);
		}
		//重置内部数据指针
		function rewind()
		{
			$this->currentIndex=0;
		}
		//判断数据指针当前位置是否还存在更多数据
		function valid()
		{
			return $this->currentIndex<$this->count; //true即为vaild
		}
		//返回数据指针值
		function key()
		{
			return $this->currentIndex;
		}
		//返回当前数据指针指向的数据
		function current()
		{
			return $this->obj->data[$this->currentIndex];
		}
		//向后移动数据指针1step
		function next()
		{
			$this->currentIndex++;
		}
	}
	
	class Object implements IteratorAggregate
	{
		public $data=array();
		function __construct($in)
		{
			$this->data=$in;
		}
		function getIterator()
		{
			return new ObjectIterator($this);
		}
	}

	$myObject=new Object(array(2,4,6,8,10));   //data改为一个array
	$myIterator= $myObject->getIterator();     //data的地址传入迭代器
	for($myIterator->rewind();$myIterator->valid();$myIterator->next())
	{
		$key=$myIterator->key();
		$value=$myIterator->current();
		echo $key."=>".$value."<br />";
	}
	echo "<br />";
?>

结果如下

这个其实还比较容易,但是如果复杂了呢,或者是用了别的迭代方式么,不论内部实现怎么变化,数据接口都是固定的,不用我们多费心,这就是迭代器的作用

3.生成器

生成器怎么说了也算是在迭代中使用的,而且比迭代器简单且容易理解,如果能用生成器的话,我个人倾向于直接while、for之类的,这里就不做介绍了

4.反射API

这个操作有点像爬去类的结构的爬虫?

如果我们手里有一些类的文档,但是不熟悉,变量很复杂,很容易看的一头雾水,这个时候这个操作就很有用了,来个例子比较直观

<?php
	class Page
	{
		public $content;
		public $title="TLA Consulting Pty Ltd";
		public $keywords="TLA Consulting, Three Letter Abbreviation, some of my best friends are search engines";
		public $buttons=["Home"=>"12_home.php",
						 "Contact"=>"12_contact.php",
						 "Services"=>"12_services.php",
						 "Site Map"=>"12_map.php"];
		//class Page's operations
		public function __set($name,$value)
		{
			$this->$name=$value;
		}
		public function Display()
		{
			echo "<html>\n<head>\n";
			$this->DisplayTitle();
			$this->DisplayKeywords();
			echo "</head>\n<body>\n";
			$this->DisplayHeader();
			$this->DisplayMenu($this->buttons);
			echo $this->content;
			$this->DisplayFooter();
			echo "</body>\n</html>\n";
		}
		public function DisplayTitle()
		{
			echo "<title>".$this->title."</title>";
		}
		public function DisplayKeywords()
		{
			//<meta> 标签永远位于 head 元素内部
			//元数据总是以名称/值的形式被成对传递的
			echo "<meta name='keywords' content='".$this->keywords."'/>";
			echo "<title>".$this->title."</title>";
		}
		public function DisplayHeader()
		{
			?>
			<!-- page header -->
			<header>
				<img src="./11.jpg" alt="TLA logo" height="200" width="600"/>
				<h1>TLA Consulting</h1>
			</header>
			<?php
		}
		public function DisplayMenu($buttons)
		{
			echo "<!--menu-->
			<nav>";
			while(list($name,$url)=each($buttons))
			{
				$this->DisplayButton($name,$url,!$this->IsURLCurrentPage($url));
			}
			echo "</nav>\n";
		}
		public function IsURLCurrentPage($url)
		{
			//例如,在地址为 http://example.com/foo/bar.php 的脚本中使用 $_SERVER['PHP_SELF'] 将得到 /foo/bar.php
			if(strpos($_SERVER['PHP_SELF'],$url)===false)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		public function DisplayButton($name,$url,$active=true)
		{
			if($active)
			{
				?>
				<div class="menuitem">
					<a href="<?=$url?>">
						<img src="./1.jpg" alt="" height="50" width="50"/>
						<!-- ?=?可以在html中表示php的属性值 -->
						<span class="menutext"><?=$name?></span>
					</a>
				</div>
				<?php
			}
			else
			{
				?>
				<div class="menuitem">
					<img src="./1.jpg" alt="" height="50" width="50"/>
					<span class="menutext"><?=$name?></span>
				</div>
				<?php
			}
		}
		public function DisplayFooter()
		{
			?>
			<!-- page footer -->
			<footer style="background: #ccccff;">
				<p>TLA Consulting Pty Ltd.<br />
				Please see our legal information page.</p>
			</footer>
			<?php
		}
	}
?>

上面这是我们的一个类,东西还是蛮多的对于我这个菜鸡来说,我们接下来用反射API来爬取

<?php
	//反射API
	require_once("12_page.php");
	$class =new ReflectionClass("Page");
	echo "<pre>".$class."</pre>";	
?>

结果如下

对我这种菜鸟帮助还蛮大的,能一眼看出一个类大概的操作和结构

5.延迟静态绑定

这是继承里的操作,下面这个例子的输出可以很好地解释

<?php
	class A
	{
		public static function whichclass()
		{
			echo __CLASS__; //使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类
		}
		public static function test()
		{
			self::whichclass();
		}
	}
	class B extends A
	{
		public static function whichclass()
		{
			echo __CLASS__;
		}
	}
	A::test();
	echo "<br />";
	B::test();
?>

输出结果如下

两个A,而不是A B

我们要解决这个问题很简单,把self改成static就好啦,可以试一下哦

6.多重继承?(Trait)

对不起,PHP没有多重继承,但是可以用别的方法实现,比如Trait,又比如接口

Trait对我来说感觉好的地方就是他强调的代码重用是包含了实现的,因人而异吧,接口的话比较快捷,Triat组合起来我觉得还蛮爽的

<?php
	trait fileLogger
	{
		public function logmessage($message,$level="DEBUG")
		{
			//code
		}
	}
	trait sysLogger
	{
		public function logmessage($message,$level="ERROR")
		{
			//code
		}
	}
	class fileStorage
	{
		use fileLogger,sysLogger
		{
			fileLogger::logmessage insteadof sysLogger;
			sysLogger::logmessage as logsymessage;
		}
		function store($data)
		{
			$this->logmessage($message);
			$this->logsymessage($message);
		}
	}
?>

上述代码就体现Trait的组合特点,而且我们可以看到如果遇到重名的函数,可以用instead和as来轻松解决,这样新的类就可以使用你所需要的Trait了,继承不同Trait,但不是直接继承不同的类的部分,算是一种模拟的多重继承吧,用起来有时候有不错的效果,而且很灵活,可是随时给类“打补丁”

猜你喜欢

转载自blog.csdn.net/qq_42192672/article/details/84349515