代码之家  ›  专栏  ›  技术社区  ›  Timo Huovinen

对象内的php对象,获取顶级对象实例

  •  5
  • Timo Huovinen  · 技术社区  · 15 年前

    我正在用PHP OOP进行试验

    我想知道的是,是否可以使用在该对象实例中创建的对象访问对象实例?

    听起来很混乱,下面是一个例子:

    索引内容

    
        class mainclass {
            var $data;
            function __construct($data){
                $this->data = $data;
            }
            function echodata(){
                echo $this->data;
            }
            function start($classname){
                include $classname.'.php';
                $inner = new $classname();
                $inner->show();
            }
    
        }
    
        $mainclass = new mainclass('maininfostuff');
        $mainclass->start('innerclass');
    
    
    
        //i want it to echo "maininfostuff"
    

    innerClass.php的内容

    
    class innerclass{
            function show(){
                mainclass->echodata();//the problem is here
            }
    }
    

    这个测试用例的目的是让内部类决定是否/何时运行主类echodata函数。

    如何完成上述示例?(不依赖静态类、单例类或扩展类)

    编辑: 由于答案有些混乱,我编辑了这个例子。

    9 回复  |  直到 15 年前
        1
  •  8
  •   Scott Saunders    15 年前

    在PHP中不能使用内部类。所以你不能在mainClass中声明你的innerClass。因为你不能这么做,所以没有办法访问外部类变量,比如Java。

    您可以这样做:

     class mainclass {
         var $data;
         function __construct($data){
             $this->data = $data;
         }
         function echodata(){
             echo $this->data;
         }
         function start(){
             $inner = new innerclass();
             $inner->show($this);
         }
    
     }
     class innerclass{
         function show($mainclass){
             $mainclass->echodata();//the problem is here
         }
     }
    
     $mainclass = new mainclass('maininfostuff');
     $mainclass->start();
    
        2
  •  4
  •   Ignacio Vazquez-Abrams    15 年前

    内部类访问外部类的唯一方法是将外部实例传递给内部类的构造函数,并将其保存在实例变量中。

        3
  •  4
  •   nickf    15 年前

    我个人从未见过 以前在另一个类的方法中定义的,所以如果它确实有效,我会非常惊讶。(我更惊讶于你为什么想要/需要这个,但无论如何…)

    构造当前(外部)对象时,只需将其传递给内部对象。

    class InnerClass {
        var $outer;
        function __construct(&$outer) {
            $this->outer = $outer;
        }
        function someStuff() {
            $this->outer->doStuff();
        }
    }
    
    $innerObj = new InnerClass($this);
    
        4
  •  3
  •   Don    15 年前

    不,内部类不在PHP中。

    “该功能已经在其他语言中可用,但问题是PHP中是否需要它。简短的答案是否定的。对于PHP执行模型,它将进一步减慢和膨胀PHP编译。-- http://jacobsantos.com/2006/general/dont-advocate-subclasses/comment-page-1/

        5
  •  1
  •   Peter Stuifzand    15 年前

    看来你应该这样做:

    class mainclass {
        var $data;
        function __construct($data){
            $this->data = $data;
        }
        function echodata(){
            echo $this->data;
        }
        function start(){
            class innerclass(){
                var $mainclass;
                function __construct($mainclass) {
                    $this->mainclass = $mainclass;
                }
                function show(){
                    $this->mainclass->echodata();//the problem is here
                }
            }
            $inner = new innerclass($this);
            $inner->show();
        }
    
    }
    
    $mainclass = new mainclass('maininfostuff');
    $mainclass->start();
    

    但在PHP中似乎不能这样做:

    Fatal error: Class declarations may not be nested in test.php on line 11
    

    所以从主类中提取您的内部类。

        6
  •  1
  •   Pekka    15 年前

    否。将对象创建为其他对象的成员时:

    $this->my_new_object = new classname(a,b,c);
    

    据我所知,没有办法访问父元素。创建对象时,必须将对父元素的引用传递给该对象:

    class innerclass(){
    
      private $parent; // Reference to the parent object
    
     function __construct(&$parent)
       {
       $this->parent = $parent; 
       }
    
    function show(){
       $this->parent->echodata();
      }
     }
    

    尽管类定义可能存在,但它永远不应该存在于函数中。 类定义可以有一个层次结构-它们可以相互扩展。但它是用 extends . 一类CAN extend 另一个。它们的定义仍然是并排的,它们不嵌套在代码中。

    我不知道你想做什么,但也许你在找什么 扩展类。在这种情况下,可以使用 parent 关键词:

    function show(){
    parent::echodata();
    }
    

    然而,这与你现在所做的完全不同。

        7
  •  1
  •   Dereleased    15 年前

    让我讲一句重要的话:

    mainclass->echodata();//the problem is here
    

    在php中,为了使用infix对象访问操作符( -> )左侧参数必须是一个变量(前面至少有一个变量 $ )并且必须是类的实例,例如 $myClass->whatever $this->foo .

    如果您来自另一种语言,并且考虑静态访问,则必须使用正确的运算符,即 :: ,例如 someClass::$someValue someClass::SOME_CONST .

    现在,如果您坚决反对将“parent”对象传递给子类的构造函数,那么您可以考虑使用单例模式,它允许您从代码中的任何位置静态访问父类的(唯一)实例,包括子对象。

    但是说真的,只要把它作为参数传递给构造函数,就像其他人说的那样,不要在函数内部定义类,特别是如果函数本身是另一个类的成员。如果该函数被调用两次,您将得到一个致命的错误。

    编辑

    下面是我所说的一个例子:

    class mainClass {
        private static $instance = null;
        private $data = null;
    
        private function __construct($setData) {
            if (!is_null($setData)) {
                $this->data = $setData;
            }
        }
    
        public static function getInstance($setData = null) {
            if (is_null(self::$instance)) {
                self::$instance = new mainClass($setData);
            }
            return self::$instance; // objects will always be passed by reference
        }
    
        public function echodata() {
            echo $this->data;
        }
    
        public function start() {
            $inner = new innerClass;
            $inner->show();
        }
    }
    
    class innerClass {
        function show() {
            mainClass::getInstance()->echodata();   
        }
    }
    

    然后运行:

    $foo = mainClass::getInstance('Foo');
    $foo->start(); // prints "Foo"
    
        8
  •  0
  •   user229044    15 年前

    您正试图用代码静态地调用非静态方法

    mainclass->echodata();//the problem is here
    

    相反,您需要传递 mainclass 子类:

     <?php
    
     class innerclass(){
         function innerclass($parent) {
             $this->_parent = $parent // hold onto our parent
         }
    
         function show(){
             $this->_parent->echodata();
         }
      }
    
      // ....
    
      $inner = new innerclass($this);
      $inner->show();
      ?>
    
        9
  •  0
  •   Timo Huovinen    15 年前

    我找到了更多的方法

    class innerclass{
            function show(){
                mainclass::echodata();
            }
    }
    class mainclass {
        var $data;
     protected static $_instance;
        function __construct($data){
            $this->data = $data;
            self::$_instance = $this;
        }
        //run previosuly declared mainclass method from anywhere
        public static function echodata(){
        if( self::$_instance === NULL ) {
            self::$_instance = new self();
        }
            self::$_instance->runechodata();
        }
        function runechodata(){
            echo $this->data;
        }
        function start($classname){
            $inner = new $classname();
            $inner->show();
        }
    
    }
    
    $mainclass = new mainclass('maininfostuff');
    $mainclass->start('innerclass');
    
    
    
    
    //i want it to echo "maininfostuff"
    

    我也喜欢这个,因为它很整洁。

    class sharing {
     protected static $mainclass;
     function echodata(){
      self::$mainclass->echodata(); 
     }
    }
    class innerclass extends sharing {
            function show(){
                parent::echodata();
            }
    }
    class mainclass extends sharing {
        var $data;
        function __construct($data){
            $this->data = $data;
      parent::$mainclass = $this;//share $this
        }
        function echodata(){
            echo $this->data;
        }
        function start($classname){
            $inner = new $classname();
            $inner->show();
        }
    
    }
    
    $mainclass = new mainclass('maininfostuff');
    $mainclass->start('innerclass');
    

    这里有一个我刚刚创建的对象实例共享类:)

    //PHP Object Sharing 
    class sharing {
     //list the classes that you would like to be available for sharing
     protected static $mainclass;
    
    
     //run any function that is shared (part of any of the shared objects)
     public function __call($name,$args){
      $shared_objects = get_class_vars(get_class());
      foreach($shared_objects as $sharedObject){
       if (method_exists($sharedObject,$name)){
        $classname = get_class($sharedObject);
        self::$$classname->$name(implode(', ',$args));
        return;
       }
      }
     }
    }
    
    
    class innerclass extends sharing {
            function show(){
       $data = 'inner says hi';
                parent::echodata($data);
            }
    }
    class mainclass extends sharing {
        var $data;
        function __construct($data){
            $this->data = $data;
      parent::$mainclass = $this;//share mainclass with anything that is a part of sharing
        }
        function echodata($moredata=NULL){
            echo $this->data.'+'.$moredata;
        }
        function start($classname){
            $inner = new $classname();
            $inner->show();
        }
    
    }
    
    $mainclass = new mainclass('maininfostuff');
    $mainclass->start('innerclass');
    
    //returns "maininfostuff+inner says hi"
    

    这允许您从任何共享对象运行任何共享的“对象实例”函数 现在,mainClass可以包含/运行它想要的任何innerClass,而innerClass可以运行mainClass实例函数,就像它已经启动的mainClass对象一样。