• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

ExSystem

@FreePascal
  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Framework DSW项目周记1

PHP动态泛型

本周实现了一个基于PHP的动态泛型方案。现在PHP可以按照下面的例子来使用泛型了:

<?php
require_once 'FrameworkDSW/System.php';
/**
 * @param <T, P>   <--这里是推荐的phpDoc定义方式
 */
class TChild extends TObject {
    /**
     * @param	T	$p
     */
    public function Func($p) {
        try {
            TType::Type($p, $this->GenericArg('T'));
        }
        catch (EInvalidTypeCasting $e) {
            echo get_class($e) . ' ($p is <div style="border: 1px solid"> ' . var_export($p, true) . '</div>)<br/>';
        }
    }

    /**
     * @param	T	$t
     * @param	P	$p
     */
    public function FuncTwo($t, $p) {
        try {
            TType::Type($t, $this->GenericArg('T'));
        }
        catch (EInvalidTypeCasting $e) {
            echo get_class($e) . ' ($t is <div style="border: 1px solid"> ' . var_export($t, true) . '</div>)<br/>';
        }
        try {
            TType::Type($p, $this->GenericArg('P'));
        }
        catch (EInvalidTypeCasting $e) {
            echo get_class($e) . ' ($p is <div style="border: 1px solid"> ' . var_export($p, true) . '</div>)<br/>';
        }
    }
}
echo '<p>TEST 1</p>';
TChild::PrepareGeneric(array ('T' => 'integer')); //相当于TChild<T: integer>
$obj = new TChild();
$obj->Func(0);
$obj->Func(new TObject()); //此处出错!不是integer
$obj->Func(true); //不出错,因为true是可以转换成1的,根据PHP的==号规则
$obj->Func('string'); //不出错,因为可以转换成0,根据PHP的==号规则

echo '<p>TEST 2</p>';
TChild::PrepareGeneric(array ('T' => 'integer', 'P' => 'TObject'));
$obj = new TChild();
$obj->FuncTwo(0, new TObject());
$obj->FuncTwo(new TObject(), 0); //出错,TObject不是integer,0不是TObject

class TComplex extends TObject {
    /**
     * 
     * @param	T	$t
     */
    public function Func($t) {
        TType::Type($t, $this->GenericArg('T'));
    }
}

echo '<p>TEST 3</p>';
TChild::PrepareGeneric(array ('T' => 'integer', 'P' => 'boolean'));
$c = new TChild();
TComplex::PrepareGeneric(array ('T' => array ('TChild' => array ('T' => 'integer', 'P' => 'boolean'))));
$obj = new TComplex();
$obj->Func($c);
$obj->Func(true);//出错:true不是TChild<T: integer, P: boolean>

注意我们的框架中的泛型是动态泛型。所谓的动态泛型就是在新建对象或者调用静态方法时,可以动态的指定泛型参数,而定义类或者静态方法时不需要指定所需要的泛型参数定义(虽然这个不是好习惯对于我来说,但是保证了PHP的灵活性),也就是说,在Java中需要这样定义和使用:

class Sample<T, P> {
	public static <Q> void Foo(Q param) { /*...*/ }
	public static void main(String[] args) {
		Sample<String, Integer> s = new Sample<String, Integer>(); //类的泛型
		Sample.<Integer>Foo(100); //泛型方法
	}
}

而现在在PHP里面可以这样使用:

/**
 * @param	<T, P>
 */
class TSample extends TObject {
	/**
	 * @param	Q	$param
	 */
	public static function Foo($param) { /*...*/ }
}

TSample::PrepareGeneric(array ('T' => 'string', 'P' => 'integer'));
$s = new TSample();

TSample::PrepareGeneric(array ('X' => 'string', 'Y' => array( 'TSample' => array ('Z' => 'string'))));
$s2 = new TSample();
//动态就在这里体现出来了,现在$s2拥有的泛型参数和$s是完全不同的。
//$s的是<T: string, P: integer>
//$s2的是<X: string, Y: TSample<Z: string>>

TSample::PrepareGeneric(array ('Q' => 'integer'));
TSample::Foo(100);

TSample::PrepareGeneric(array ('P' => 'string'));
TSample::Foo(100);
//这个是方法泛型的动态。

最后,附上相关的API:

void TObject::PrepareGeneric(array $Args)
//为下次创建对象或调用静态方法准备泛型的参数,如果需要的话。
mixed TObject::GenericArgs()
//返回当前对象所有泛型参数的值。
mixed TObject::GenericArg(string $ArgName)
//返回当前对象特定泛型参数名称的泛型参数值。
mixed TObject::StaticGenericArgs()
//返回当前类的泛型参数值,泛型静态方法用。
mixed TObject::StaticGenericArgs(string $ArgName)
//返回当前类的某一泛型参数的值,泛型静态方法用。
boolean TObject::IsInstanceOf(mixed $Type)
//判断当前对象是不是$Type描述的类型。
mixed TObject::ObjectType()
//返回当前对象的类型信息。

void TType::Type(mixed &$Var, mixed $Type)
//确保$Var是$Type类型的变量。
void TType::Obejct(object &$Var, mixed $Type)
//确保$Var是$Type类型的对象。

接下来将要实现的是统一数据库访问接口和对容器框架的泛型化……

posted on 2010-05-01 14:12  ExSystem  阅读(1006)  评论(4)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3