精华内容
下载资源
问答
  • 原文地址: https://blog.unlink.link/php/php_runtime_instance_class_and_pass_parameters.html/comment-page-1 ...什么是动态实例化对象呢?我们先来看一下PHP有一种变量函数(可变函数)的概念,例如如

    原文地址: https://blog.unlink.link/php/php_runtime_instance_class_and_pass_parameters.html/comment-page-1


    在框架开发,模块化开发等场合,我们可能有一种需求,那就是在PHP运行时动态实例化对象。
    什么是动态实例化对象呢?我们先来看一下PHP有一种变量函数(可变函数)的概念,例如如下代码:

    function foo() {
        echo 'This is the foo function';
    }
    $bar = 'foo';
    $bar();
    运行上述代码将会输出“This is the foo function”。具体请参考PHP手册:可变函数。当然,如果需要动态调用的话,那么就使用call_user_func或call_user_func_array函数。这两个函数的用法不是本文的重点,不懂的同学请查阅其它资料。回到本文的话题上:什么是动态实例化对象?本人认为动态实例化对象,即是:需要实例化的对象是在程序运行时(run-time)动态决定(由变量决定)需要实例化什么样的对象,而不是直接写死在代码里。
    通过上述例子我们已经知道了如何在运行时动态调用一个函数了,在现在面向对向如此流行的今天,在一些代码中,我们需要去动态去实例化一个类,该怎么做呢?
    情况一:类的构造函数没有参数或参数的个数是确定的
    如果类的构造函数没有参数或者我们要实例化的类根本没有构造函数,似乎简单一点,可以照上面的例子改一个嘛,嗯,照葫芦画瓢,谁不会:
    代码示例:(构造函数没有参数)
    class FOO {
        private $a, $b;
        public function __construct() {
            $this->a = 1;
            $this->b = 2;
        }
        public function test() {
            echo 'This is the method test of class FOO<br />';
            echo '$this->a=', $this->a, ', $this->b=', $this->b;
        }
    }
    $bar = 'FOO';
    $foo = new $bar();
    $foo->test();
    运行一下,就看到了输出了如下结果:
    This is the method test of class FOO
    $this->a=1, $this->b=2
    嗯,我们要传参的话,那么就这样吧:
    class FOO {
        private $a, $b;
        public function __construct($a, $b) {
            $this->a = $a;
            $this->b = $b;
        }
        public function test() {
            echo 'This is the method test of class FOO<br />';
            echo '$this->a=', $this->a, ', $this->b=', $this->b;
        }
    }
    $bar = 'FOO';
    $foo = new $bar('test', 5);
    $foo->test();
    一样可以得到类似的结果:
    This is the method test of class FOO
    $this->a=test, $this->b=5
    很理想嘛。
    情况二:类的构造函数的参数个数不确定
    这种情况就要麻烦很多了,但是如果要写得比较通用的话,就不得不考虑这种情况了。例如,我们有如下两个类
    class FOO {
        public function test() {
            echo 'This is the method test of class FOO';
        }
    }
    class BAR {
        private $a, $b;
        public function __construct($a, $b) {
            $this->a = $a;
            $this->b = $b;
        }
        public function test() {
            echo 'This is the method test of class BAR<br />';
            echo '$this->a=', $this->a, ', $this->b=', $this->b;
        }
    }
    我们想要一个通用的方式来实例化这两个类。我们注意到FOO类是没有写构造函数的,或者是可以认为FOO类的构造函数的参数个数为零;而BAR类的构造函数却有参数。还好,PHP5已经足够强大了,引入了反射的概念,具体请参考PHP手册:反射,虽然手册上也没有什么可参考的:)。还好,命名写得不错,从类名和方法名上面已经可以看出大概的端倪,不需要太多的文字。
    那么好吧,就让我们用PHP5的反射来着手这个事情:
    (还在用PHP4的同学请不要走开,如果你拥有一个没有反射的PHP版本或者是你为了兼容也好还是不想升级也好,反正不想用反射的,下面有解决方案)
    $class = new ReflectionClass('FOO');
    $foo = $class->newInstance(); //或者是$foo = $class->newInstanceArgs();
    $foo->test();
    看到什么了没有?接着来:
    $class = new ReflectionClass('BAR');
    $bar = $class->newInstanceArgs(array(55, 65));
    $bar->test();
    OK,似乎可以了,那么就整理一下吧,来个通用函数,我们想这么设计,此函数的第一个函数是要实例化的类名,从第二个参数开始就是要实例化类的构造函数的参数,有几个就写几个上去,没有就不写。要想实现参数个数可变的函数,我们有两种方法:
    第一种是类似于:
    function foo($arg1, $arg2 = 123, $arg3 = 'test', $arg4 = null, ....... ) {
        //some code;
    }
    的办法,这种方法有两个缺点,第一个是你如果需要传100个参数难道就写100个参数吗?第二个是你还要在程序里判断哪个参数是不是null,或是其它默认值。(题外话:这种写法的参数默认值必须放在最后,你不能将没有默认值的参数插在有默认值的中间或前面,否则你调用的时候也必须显式地写上有默认值参数的值)
    另一种实现参数数量可变的方法是在函数里用PHP的内置函数func_get_args(猛击这里看手册)取得传给函数的参数。类似的函数有func_get_num和func_get_arg,算了,我懒,你们自己找手册看吧。
    那么,用这个函数似乎要方便很多,我们根据想象的函数参数的排列,代码应该是这个样子的:
    function newInstance() {
        $arguments = func_get_args();
        $className = array_shift($arguments);
        $class = new ReflectionClass($className);
        return $class->newInstanceArgs($arguments);
    }
    OK,让我们来看一下效果:
    $foo = newInstance('FOO');
    $foo->test();
    //输出结果:
    //This is the method test of class FOO
     
    $bar = newInstance('BAR', 3, 5);
    $bar->test();
    //输出结果:
    //This is the method test of class BAR
    //$this->a=3, $this->b=5
    短短四行代码,效果相当完美啊。那么,如果应用到类里面,我们可以利用这种思想,直接写成魔术方法,可以让我们的类更酷哦!
    class INSTANCE {
        function __call($className, $arguments) {
            $class = new ReflectionClass($className);
            return $class->newInstanceArgs($arguments);
        }
    }
    $inst = new INSTANCE();
    $foo = $inst->foo();
    $foo->test();
    //输出结果:
    //This is the method test of class FOO
     
    $bar = $inst->bar('arg1', 'arg2');
    $bar->test();
    //输出结果:
    //This is the method test of class BAR
    //$this->a=3, $this->b=5
    咔咔,爽吧。
    接下来讨论一下不使用反射类的情况。例如PHP4中就没有反射,而一些老项目就是运行在PHP4上面的。或者是要保证项目对未知环境的兼容性,Whatever,来关心一下怎么动态传参吧。PHP中动态传参的函数只有一个:call_user_func_array(轻击此处查看手册)。这是一个动态调用函数的函数,作用是可以将函数的参数以数组的形式传递给要调用的函数。好吧,我自己也被自己绕晕了,直接来看实例:
    function foo($a, $b) {
        echo '$a=', $a, '<br />';
        echo '$b=', $b;
    }
    call_user_func_array('foo', array(1, 'string'));
    //本例输出结果:
    //$a=1
    //$b=string
    那么,要实现用这种方法来动态实例化对象并传参,呃……,只有曲线救国了,我们得先写一个函数,让这个函数来实例化对象,而这个函数的参数就原原本本地传给要实例化对象的类的构造函数就好了。打住!那这个函数得有几个参数啊?怎么实现传递不同个数的参数呢?嘿嘿,我一声冷笑,你忘了PHP里提供一个创建匿名函数的函数吗?(又开始绕起来了……)create_function(手册在此),照着手册里面的例子直接画就可以了,我也懒得打字了,直接看下面的代码,注释我写清楚点大家都明白了:
    function newInst() {
        //取得所有参数
        $arguments = func_get_args();
     
        //弹出第一个参数,这是类名,剩下的都是要传给实例化类的构造函数的参数了
        $className = array_shift($arguments);
     
        //给所有的参数键值加个前缀
        $keys = array_keys($arguments);
        array_walk($keys, create_function('&$value, $key, $prefix', '$value = $prefix . $value;'), '$arg_');
     
        //动态构造实例化类的函数,主要是动态构造参数的个数
        $paramStr = implode(', ',$keys);
        $newClass=create_function($paramStr, "return new {$className}({$paramStr});");
     
        //实例化对象并返回
        return call_user_func_array($newClass, $arguments);
    }
    好了,至于效果是什么,就麻烦各位看官自己动动手,运行一下看看,是不是自己期望的结果。
    如果改写成类里面的魔术方法,哼哼,威力嘛,你懂的!然后呢,我还是懒了,如果要写成魔术方法的话,相信这么easy的事情你很轻松就办到了。就当一个作业吧。另,本文的代码都是本人运行过的,但是,写文章的时候没有使用复制/粘贴功能,所以,你最好是也不要复制粘贴。如果从本文中的代码copy下来运行出错的话,还烦请各位自己debug一下,编程不就是要自己写么。
    本来这个话题到这里就应该可以结束了,但是想到我在想到这个办法之前用的方法(好绕……),本着重在交流的态度,一起放出来。我例两个关键函数吧:extract和eval。只是我个人觉得用eval函数比较山寨,能不用最好不用。于是又想出了上面的办法,哈哈,编程最重要的是思想,不是吗?好,又是一道作业题了,大家可以试试用这两个函数(当然也会用到别的函数)来实现带不定数量的参数动态实例化对象的函数。
    展开全文
  • 实例化对象写法的区别 栈中实例化对象: 堆中实例化对象: 最大区别就在于,从栈中申请内存,在使用完后无需释放,但是从堆中申请内存,使用完以后必须释放! 注意:从堆中申请内存,是有可能失败的,所以...

    一. 实例化对象写法的区别

    栈中实例化对象:

    堆中实例化对象:

    最大区别就在于,从栈中申请内存,在使用完后无需释放,但是从堆中申请内存,使用完以后必须释放!

    注意:从堆中申请内存,是有可能失败的,所以要加上对于申请内存是否成功的判断!

    二. 访问对象成员的区别

    展开全文
  • java实例化对象

    千次阅读 2016-05-15 08:35:19
    摘要:分享牛,分享牛分享,java类加载机制,java实例化对象,java实例化对象机制,java基础。java是如何实例化对象的呢?以及实例化对象的先后顺序是什么?下面我们以测试的方式说明.1.1. 声明父类public class A ...

    摘要:分享牛,分享牛分享,java类加载机制,java实例化对象,java实例化对象机制,java基础。

    java是如何实例化对象的呢?以及实例化对象的先后顺序是什么?下面我们以测试的方式说明.

    1.1. 声明父类

    public class A {
    public A() {
    a1();
    }
    public void a1() {
    System.out.println("a-a1");
    }
    }

    1.2. 声明子类

    public class B extends A {
    int a=0;
    public B() {
    a=100;
    }
    @Override
    public void a1() {
    System.out.println("B a1():"+a);
    System.out.println("B a1()");
    }
    }

    1.3. 测视类

    1.3.1. 第一种情况

    new A();

    输出结果如下:

    a-a1

    因为a类默认继承object所以实例化A类的时候,直接调用自身的a1()方法。

    1.3.2. 第二种情况

    new A().a1();

    输出结果:

    a-a1

    a-a1

    因为a类默认继承object所以实例化A类的时候,直接调用自身的构造方法a1()方法。因为又直接调用a1()方法,所以一共调用了2次。

    1.3.3. 第三种情况

    new B();

    输出结果:

    B a1():0

    B a1()

    因为B类继承a类,所以先去实例化父类A类,但是实例化A类的时候调用a1(),发现B类重写了A类中的方法,所以调用B类的a1(),这个时候b还没有被构造函数赋值,所以是默认的值。

    1.3.4. 第四种情况

    new B().a1();

    输出结果:

    B a1():0

    B a1()

    B a1():100

    B a1()

    因为B类继承a类,所以先去实例化父类A类,但是实例化A类的时候调用a1(),发现B类重写了A类中的方法,所以调用B类的a1()方法,实例化B对象实例的时候,构造方法已经初始化为100,所以第二次输出有值。

    分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519)

    展开全文
  • 问题:不同的客户端去请求Servlet,该Servlet是同一个实例化对象还是不同的实例化对象?(即,是每次请求Servlet都会实例化一个该Servlet对象,还是每次请求都使用的是同一个Servlet对象?) 难道Servlet是单例模式吗?...
  • 声明对象和实例化对象的区别

    千次阅读 2015-11-04 11:17:20
    声明对象和实例化对象的区别

    转载自:http://www.cnblogs.com/quietwalk/archive/2010/03/29/1700033.html



    声明对象和实例化对象的区别

    ++++++++++++++++++

    先看一个神评论:


    我的理解是,打个比喻:
    人是一个类;比如你叫张伟,就是人实例化出来的一个对象。有人类的一切特征。
    但如果你将来结婚了,还没有孩子的时候,你给你的孩子取了个名字说他将来叫“张一山”。这样就只是声明了“张一山”是个人;但他什么都不能做。如果需要让他有人类的特征,和人一样,就需要把它生出来(即实例化)。

    不知道这样理解对不对·······

    ++++++++++++++++++


    在定义类时,只是通知编译器需要准备多大的内存空间,并没有为它分配内存空间。只有用类创建了对象后,才会真正占用内存空间。

     

    1. 声明对象

    对象的声明和基本类型的数据声明在形式上是一样的:

    类名 对象名;

    对象名也是用户标识符,和基本类型的变量遵循同样的命名规则和使用规则。

    声明一个变量,并不会分配一个完整的对象所需要的内存空间,只是将对象名所代表的变量看成是一个引用变量,并为它分配所需内存空间,它所占用的空间远远小于一个类的对象所需要的空间。

    如此处理,使得Java中声明一个对象的消耗很小,但也有一个副作用,就是对象不能马上使用,还需要对它进行实例化。

     

    2. 实例化对象

    用new关键字创建一个新对象,即进行实例化。格式如下:

    new 构造方法([参数列表])

    实例化的过程就是为对象分配内存空间的过程,此时,对象才成为类的实例。new所执行的具体操作是调用相应类中的构造方法(包括祖先类的构造方法),来完成内存分配以及变量的初始化工作,然后将分配的内存地址返回给所定义的变量。

    实质:实例化了就有自己内存空间。而没有实例化就和引用的对象内存空间地址相同,指向同一个空间。





    展开全文
  • 动态实例化和静态实例化

    千次阅读 2014-09-26 18:53:06
    实例化:创建一个对象的过程 静态实例化:在编译时刻完成的实例化 动态实例化:在运行时刻完成的实例化 Java语言都是动态实例化
  • 普通类实现字符串创建实例: var type =Assembly.Load("SqlSugar").GetType("SqlSugar.SqlServerDb"); IDb IDb=(IDb)Activator.CreateInstance(type, true); 泛型类就比较坑了,花了我一些时间,下面是泛型类的使用...
  • 调用有参构造实例化对象

    千次阅读 2016-07-18 15:22:44
    调用有参构造实例化对象
  • 通过无参构造实例化对象

    千次阅读 2016-07-18 15:08:09
    通过无参构造实例化对象
  • java反射实例化对象

    千次阅读 2018-06-08 13:43:41
    可通过Class类提供的方法为一个类实例化对象,区别与new关键字创建对象,前者是在类已经编译好的情况下,通过指定类名来创建实例化对象,后者是在编译之后之间创建实例化对象。也可通过Class类在运行时获得某个类...
  • 上面这种情况很多时候会遇到,直接使用了car的tires属性,但是Car类确实是实例化了,但是其中的tires属性在从ts转到js的时候, 并不会被实例化。 所以可以给这个属性赋个空的数组。 car.tires = [];
  • C# 实例化对象

    千次阅读 2018-03-14 16:05:46
    实例化对象,其实就是创建对象过程;要用一个类中的一个方法。如果这个类是静态类,那么ok,可以直接调用这个方法。可是如果这个类不是静态类呢?就需要用对象来引用这个方法了。那么对象如何来呢?就需要new一下了...
  • 3.2、抽象一个类和实例化对象

    千次阅读 2018-03-28 19:20:36
    一、抽象一个类 二、实例化对象 1、实例化对象 2、对象类型在内存中分配情况 三、$this 四、构造函数和析构函数
  • 想python那样在实例化对象后,给这个对象添加函数和属性。路过的大神指点指点吧
  • java实例化对象时程序运行顺序

    千次阅读 2014-08-11 17:23:07
    java实例化对象时程序运行顺序
  • 与new运算符一起使用来实例化对象。 举例: function Person(){} //Person构造函数 var p=new Person(); //Person构造函数创建对象,也可叫做实例化 二、什么是原型? 原型:构造函数在实例化对象的过程中,系统...
  • C++类的实例化对象

    千次阅读 2018-09-02 18:47:11
    C语言使用函数对内容进行封装的,而C++是用类进行封装的 ...类在创建实例化对象时,类本身并不被分配空间 类对象包括类里的成员变量 若计算类的大小,只需计算成员变量大小之和,但要注意内存对齐 空类大小为一个...
  • 用spring管理和实例化对象的四种方式 方式一:无参构造函数(最常用) 对象是spring创建,创建的对象还要交给spring容器管理 bean:豆子 id:在spring容器中Hello对象的名,在容器中id的值必须唯一 class:要对哪个类实例化...
  • 就自定义的类而言(非抽象类)生成的对象,有实例化对象(有动态内存分配),也有生成对象(无动态内存分配)。此时可以说"实例化对象"(动态内存分配),"生成对象"(无动态内存分配)。 总结简记:没有分配内存的都是生成对象,...
  • 私有化构造方法如何实例化对象

    千次阅读 2019-04-16 17:02:47
    私有的构造方法如何创建对象 在java中,对象的创建都是由构造方法实现的,如果将构造方法私有,根据private的用法,就只能在类的内部创建类的对象。外部又怎么得到这个对象呢,是否可以提供一个public方法返回在...
  • 那么怎么完成实例化呢。我们创建一个对象需要对它初始化数据。能够有这一作用的是什么呢?——构造函数。所以就有了 Car mycar= new Car(); 当我们自己定义了与类同名的有参构造函数时,假设参数类型是整型的,...
  • C++实例化对象数组

    万次阅读 2017-08-02 10:46:52
    从栈中实例化Coordinate coor[3]; Coor[0].m_iX = 3; coor[0].m_iY = 5;从堆中实例化Coordinate *p = new Coordinate[3]; p->m_iX = 11; p[0].m_iY = 13; p++; p->m_iY = 9;p = coor[0]; delete []p; p = NULL;
  • 实例化对象的三种方法

    万次阅读 2019-05-18 23:59:29
    1.任何类的实例化对象可以通过Object类中的getClass()方法取得Class类对象 public class Test { public static void main(String[] args) { Date date=new Date(); Class aClass = date.getClass(); System.....
  • Objenesis,另一种实例化对象的方式

    千次阅读 2018-05-27 23:10:44
    由于不是所有的类都有无参构造器又或者有的类构造器是private等,在这样的情况下,如果我们还想实例化对象,class.newInstance是无法满足的。使用public class Test { private int i; public Test(int i){ this....
  • java实例化对象后面添加花括号的理解分析 昨天在看MyBatis官方文档时看到这么一段代码 return new SQL() {{ SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME"); FROM("PERSON P"); if ...
  • Java通过泛型的模板类型实例化对象

    千次阅读 2018-06-08 14:14:02
    通过泛型的模板类型实例化对象 最近自己研究了下mvvm框架,使用泛型的方式可节省很多代码,并且可以合并很多冗余代码,为了最大化的精简代码想到了通过泛型的type用反射的方式实例化对象,这样对象的实例化代码就...
  • 如果你在写Layabox对象池的时候不小心看到这篇文章,那么恭喜你,...1、通过类型获取类型名并实例化一个对象,下面是我写的一个在对象池中根据类型名取出一个对象实例化一个对象的方法。重点是ClassZ.name /** ...
  • C++只在栈或堆上实例化对象

    千次阅读 2017-03-10 14:42:26
    C++如何让类对象只能在堆(栈)上分配空间一般情况下写一个类都是可以采用new在堆...1.静态实例化对象 如 A a;的步骤为:先由编译器为对象在栈空间分配内存,移动栈顶指针,挪出适当的空间,然后在这个空间上调用构造函

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,721,221
精华内容 688,488
关键字:

动态实例化对象