PHP面向对象杂谈

        PHP5.0还没有命名空间的概念,所以通常类文件的加载都是通过require,require_once,include,include_once. include()和require()语句的不同在于它们如何处理错误。使用require()调用文件发生错误时,将会停止整个程序;调用Include()时遇到相同的错误,则会生成警告并停止执行包含文件,跳出调用代码然后继续执行。

        require()和require_once用于包含库文件时更加安全,而include()和include_once()则适用于加载模板这样的操作。必须了解的一点是require和require_once是语句而不函数。出于安全的考虑,应尽可能使用require & require_once

        常常要加载一些基本的类文件,如果通过using命名空间来导入有时候也会过于繁杂,当然可以写一些函数来包括某些类文件,PHP5还提供了自动加载这一功能,只要实现function __autoload($classname)即可。

        动态引用类

        PHP可以动态地引用类,这一功能类似于反射,所谓的动态地引用类,只不过是给一个类的字符串,同样也可实例化对象,如下代码所示:

//TestC.php
class TestC {
	public function sayHello()
	{
		return 'hello';
	}
}

//index.php
require_once './TestC.php';
$classname = "TestC";
$pro = new $classname();
print $pro->sayHello();
      如果想让系统能够运行用户创建的插件,这个功能非常有用。在开发实际项目时,需要先检查类是否存在、它是否拥有将要使用的方法等,以避免可能存在的风险。虽然PHP5有功能更强大的反射API,然而这些类函数更加接地气,首选原因大概是它能够与PHP4兼容。
        查找类
       class_exists()函数接受表示类的字符串,检查并返回布尔值。检查一个类是否存在。代码如下:
$classname = "TestC";
$path = "./".$classname.'.php';
if(!file_exists($path))
{
	throw new Exception('No such file');
}
require_once $path;
if(!class_exists($classname))
{
	throw new Exception('No such class');
}
       get_declared_classes()函数来获得脚本进程中定义的所有类的数组。
       get_class()函数用于获取对象的类名字符串。
       对于判断一个对象是否某家族的一个对象,instanceof可以解决。
       get_class_methods()获取类的方法数组
       is_callable()函数它接受字符串变量形式的方法名作为第一个参数,如果类方法存在且可被调用,则返回true.
 也可以传递一个数组参数,数组第一个参数是类名或对象,第二个参数是方法。
       method_exists()函数检查一个类或者对象是否存在某一方法,它比is_callable低级一些。
      get_class_vars()函数返回一个类或者对象的属性数组,属性名为键名,属性值作为键值。
      get_parent_class()可以获得一个类的父类,如果不存在这样的类,则返回false.
      is_subclass_of()函数检测类是否是另一个类的派生类,它需要一个子类对象和父类的名字。如果第二个参数是第一个参数的父类的话,该函数就返回true. 一个类是否实现了某个接口不能使用这个函数来确定。
      call_user_func()可以调用方法或函数,要调用一个函数,需要将字符串作为它的第一个参数。要调用类方法,则需要一个数组,第一个参数是对象,第二个是调用的方法名。
      call_user_func_array()函数可能更好用,因为它可以传递实实在在的参数,PHP中有__call拦截器,也可以调用函数,但参数只能当成一个数组传过去,而这个函数则可以还原成对应的参数列表。       
      反射
      PHP对于反射实现了一些类,具体与下图所示:
         
     简单的查看一个类的所有信息代码如下:
$classinfo = new ReflectionClass($classname);
Reflection::export($classinfo);
       ReflectionClass接受唯一的参数:类名。Relection工具类输出类的相关信息。它有一个静态方法export(),用于格式化和输出这个类的管理的数据。
       可以使用反射类中的函数来查看关于的类的所有信息,类声明如下:类详情
ReflectionClass implements Reflector {
/* 常量 */
const integer IS_IMPLICIT_ABSTRACT = 16 ;
const integer IS_EXPLICIT_ABSTRACT = 32 ;
const integer IS_FINAL = 64 ;
/* 属性 */
public $name ;
/* 方法 */
public __construct ( mixed $argument )
public static string export ( mixed $argument [, bool $return = false ] )
public mixed getConstant ( string $name )
public array getConstants ( void )
public ReflectionMethod getConstructor ( void )
public array getDefaultProperties ( void )
public string getDocComment ( void )
public int getEndLine ( void )
public ReflectionExtension getExtension ( void )
public string getExtensionName ( void )
public string getFileName ( void )
public array getInterfaceNames ( void )
public array getInterfaces ( void )
public ReflectionMethod getMethod ( string $name )
public array getMethods ([ int $filter ] )
public int getModifiers ( void )
public string getName ( void )
public string getNamespaceName ( void )
public object getParentClass ( void )
public array getProperties ([ int $filter ] )
public ReflectionProperty getProperty ( string $name )
public string getShortName ( void )
public int getStartLine ( void )
public array getStaticProperties ( void )
public mixed getStaticPropertyValue ( string $name [, mixed &$def_value ] )
public array getTraitAliases ( void )
public array getTraitNames ( void )
public array getTraits ( void )
public bool hasConstant ( string $name )
public bool hasMethod ( string $name )
public bool hasProperty ( string $name )
public bool implementsInterface ( string $interface )
public bool inNamespace ( void )
public bool isAbstract ( void )
public bool isCloneable ( void )
public bool isFinal ( void )
public bool isInstance ( object $object )
public bool isInstantiable ( void )
public bool isInterface ( void )
public bool isInternal ( void )
public bool isIterateable ( void )
public bool isSubclassOf ( string $class )
public bool isTrait ( void )
public bool isUserDefined ( void )
public object newInstance ( mixed $args [, mixed $... ] )
public object newInstanceArgs ([ array $args ] )
public object newInstanceWithoutConstructor ( void )
public void setStaticPropertyValue ( string $name , string $value )
public string __toString ( void )
}
通过反射我们可以很容易实现查看类的源代码,一个简单的工具类如下:
class ReflectionUtil
{
	static function getClassSource(ReflectionClass $class)
	{
		$path = $class->getFileName();
		$lines = @file($path); //这里并未处理异常
		$from = $class->getStartLine();
		$to = $class->getEndLine();
		$len = $to-$from+1;
		return implode(array_slice($lines, $from-1,$len));
	}
}
当然,似乎这种方法只能显示自定义的类,也许可以改进使之可以查看更多的类的源码。
也可以很容易查看类的方法和属性,这些可以使用另外两个类ReflectionMethod及ReflectionProperty,它们可以通过ReflectionClass类的方法getMethod(getMethods)及getProperty(getProperties) 来获得.具体如何获得相关信息,可以查看这两个类的实现。ReflectionProperty   |  ReflectionMethod
      其它一些反射类可以查看PHP手册。
      下面一个摘自一本书的实例,和大家分享一下,反射除了获取类的基本信息,还有一个重要的方法:newInstance
它可以创建类的实例。
      实例概要:从配置文件中读取要实例化类的相关信息,然后实例化类,执行。也就是说这个类可以加载第三方插件。为所有的插件实现一个Module接口,它包含方法execute,有一个ModuleRunner,负责依据配置文件实例化类。所的实现了Module接口的类中的设置方法都是setProperty的形式,这样的做的原因是要能够使ModuleRunner能够识别这些方法并调用。具体代码如下:
<?php
//TestC.php
class Person{
	public $name;
	public function __construct($name)
	{
		$this->name = $name;
	}
}
interface Module{
	public function execute();
}

class PersonModule implements Module
{
	public function setPerson(Person $person)
	{
		print 'PersonModule:setPerson...this person name is '.$person->name.'<br />';
	}
	public  function execute()
	{
		print "PersonModule:execute".'<br />';
	}
}

class FtpModule implements  Module
{
	public function setHost($host)
	{
		print 'host :'.$host.'<br />';
	}
	public function  setUser($user)
	{
		print 'user :'.$user.'<br />';
	}
	public function execute()
	{
		print 'FtpModule:execute'.'<br />';
	}
}

//index.php
<?php 

require_once './TestC.php';

class ModuleRunner
{
	//由配置文件得到的配置信息,这里直接给出
	private  $config = array(
		'PersonModule' => array('person' => 'yourname'),
		'FtpModule' => array('host' => 'http://www.baidu.com',
	                    'user' => 'username'  ),
	);
	
	private $moduleArr = array();

	public function init()
	{  
		$interface = new ReflectionClass('Module');
		foreach ($this->config as $modulename => $param)
		{
			$module_class = new ReflectionClass($modulename);
			if(! $module_class->isSubclassOf($interface))
			{
				throw new Exception('unknown module type: '.$modulename);
			}
			$module = $module_class->newInstance();
			
			//对模块类的设置方法进行执行
			foreach ($module_class->getMethods() as $method)
			{   
				$this->handleMethod($module,$method,$param);
			}
			array_push($this->moduleArr, $module);
		}
	}
	
	private function handleMethod(Module $module,ReflectionMethod $method,$param)
	{
		$methodname = $method->getName();
		$args = $method->getParameters();
	    
		//不是set方法,而且这里只要求一个参数
		if(count($args)!= 1 || substr($methodname, 0,3) != 'set'){
			return false;
		}
		
		//设置参数不在时
		$property = strtolower(substr($methodname, 3));
		if(!isset($param[$property])){
			return false;
		}
		
		//确定参数的类型并执行之
		$arg_class = $args[0]->getClass(); 
		if(empty($arg_class)){//基本类型
			$method->invoke($module,$param[$property]);
		}
		else 
		{   
			//参数类型是对象,
			$method->invoke($module,$arg_class->newInstance($param[$property]));
		}
	}
	public function execute()
	{
		foreach ($this->moduleArr as $module)
			$module->execute();
	}
}

$test = new ModuleRunner();
$test->init();
$test->execute();
?>


      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
在Java中,可以使用NI-VISA库来进行GPIB接口控制,下面是一个简单的示例代码。 ```java import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import visa32.*; public class GPIBControl { private static final int GPIB_ADDRESS = 1; // GPIB地址 private static final int BUFFER_SIZE = 1024; // 缓冲区大小 public static void main(String[] args) { // 初始化NI-VISA库 VisaLibrary visaLibrary = (VisaLibrary) Native.loadLibrary("visa32", VisaLibrary.class); visaLibrary.viOpenDefaultRM(); // 打开GPIB设备 String deviceName = "GPIB0::" + GPIB_ADDRESS + "::INSTR"; Pointer instrument = new Memory(GpibLibrary.ViUInt32.SIZE); visaLibrary.viOpen(visaLibrary.getResourceManager(), deviceName, new GpibLibrary.ViAccessMode(GpibLibrary.VI_NO_LOCK), new GpibLibrary.ViUInt32(0), instrument); Pointer session = instrument.getPointer(0); // 设置超时时间 visaLibrary.viSetAttribute(new GpibLibrary.ViSession(session), new GpibLibrary.ViAttrState(GpibLibrary.VI_TMO_VALUE), new GpibLibrary.ViUInt32(5000)); // 写入命令 String command = "*IDN?"; visaLibrary.viWrite(new GpibLibrary.ViSession(session), command.getBytes(), new GpibLibrary.ViUInt32(command.length()), new IntByReference()); // 读取响应 byte[] buffer = new byte[BUFFER_SIZE]; visaLibrary.viRead(new GpibLibrary.ViSession(session), buffer, new GpibLibrary.ViUInt32(BUFFER_SIZE), new IntByReference()); String response = new String(buffer).trim(); System.out.println("Instrument response: " + response); // 关闭设备 visaLibrary.viClose(new GpibLibrary.ViSession(session)); visaLibrary.viClose(visaLibrary.getResourceManager()); } } ``` 这个示例代码使用NI-VISA库来打开GPIB设备,设置超时时间,写入命令并读取响应。需要注意的是,GPIB_ADDRESS变量需要设置为实际的GPIB地址,BUFFER_SIZE变量可以根据需要进行调整。 在实际应用中,需要根据仪器的通信协议进行编写代码,例如使用SCPI命令进行控制。希望这个示例代码能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值