Framework DSW项目周记1

本周实现了一个基于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类型的对象。

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

你可能感兴趣的:(framework)