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

时间:2010-01-29 14:50:24

标签: php object oop

我正在尝试使用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
        }
}

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

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

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

9 个答案:

答案 0 :(得分:8)

PHP中不可能使用内部类。所以你不能在mainclass中声明你的内部类。而且由于你不能这样做,所以无法访问外部类变量,例如,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();

答案 1 :(得分:4)

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

答案 2 :(得分:4)

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

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

class InnerClass {
    var $outer;
    function __construct(&$outer) {
        $this->outer = $outer;
    }
    function someStuff() {
        $this->outer->doStuff();
    }
}

$innerObj = new InnerClass($this);

答案 3 :(得分:3)

不,内部条款不在PHP中。

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

答案 4 :(得分:1)

没有。当您将对象创建为另一个对象的成员时:

$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调用的。一个班级可以extend另一个班级。他们的定义仍然是并排的,它们没有嵌套在代码中。

我不知道你要做什么,但也许你正在寻找扩展一个类。在这种情况下,您可以使用parent关键字访问父级中定义的函数和变量:

function show(){
parent::echodata();
}
然而,这与你现在正在做的事情有根本的不同。

答案 5 :(得分:1)

看来你应该这样做:

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)

让我谈一个重要的路线:

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

在PHP中,为了使用中缀对象访问运算符(->),左侧参数必须是一个变量(前面至少有一个$)并且必须是一个实例一个班级,例如$myClass->whatever$this->foo

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

现在,如果你坚决反对将“父”对象传递给子构造函数,你可以考虑使用单例模式,这样你就可以从任何地方静态访问父类的(唯一)实例。代码,包括子对象。

但严重的是,只需将它作为参数传递给构造函数,并且正如其他人所说,不要在函数内部定义类,特别是如果该函数本身是另一个类的成员。如果该函数被调用两次,则会出现致命错误。

修改

这是我正在谈论的一个例子:

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"

答案 7 :(得分:0)

您正尝试使用代码

静态调用非静态方法
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();
  ?>

答案 8 :(得分:0)

我找到了更多方法来做到这一点

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可以运行mainclass实例函数,就好像它已经启动的mainclass对象一样