объект php внутри объекта, получая экземпляр объекта верхнего уровня - PullRequest
5 голосов
/ 29 января 2010

Я экспериментирую с PHP ООП

Я пытаюсь выяснить, возможно ли получить доступ к экземпляру объекта из объекта, созданного в этом экземпляре объекта?

звучит странно, вот пример:

содержание индекса


    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
        }
}

цель этого контрольного примера - заставить внутренний класс решить, запускать ли функцию эходанных основного класса * и когда

как можно выполнить приведенный выше пример? (без использования статических классов, синглетонов или расширенных классов)

редактирование: из-за некоторой путаницы в ответах я отредактировал пример

Ответы [ 9 ]

8 голосов
/ 29 января 2010

Внутренние классы невозможны в PHP. Таким образом, вы не можете объявить свой внутренний класс в основном классе. И поскольку вы не можете этого сделать, нет никакого способа получить доступ к переменным внешних классов, как, например, в 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();
4 голосов
/ 29 января 2010

Лично я никогда не видел класс , определенный внутри методов другого класса, поэтому, если он действительно работает вообще, я очень удивлен. (Я даже больше удивлен, почему ты хочешь / нуждаешься в этом, но все равно ...)

Просто передайте текущий (внешний) объект внутреннему объекту при его создании.

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

$innerObj = new InnerClass($this);
4 голосов
/ 29 января 2010

Единственный способ для внутреннего класса иметь доступ к внешнему классу - передать внешний экземпляр конструктору внутреннего класса и сохранить его в переменной экземпляра.

3 голосов
/ 29 января 2010

Нет, внутренние предложения не в PHP.

«Функциональность уже доступна на других языках, но вопрос в том, нужна ли она в PHP. Краткий ответ - нет. С моделью исполнения PHP это еще больше замедлит и приведет к увеличению производительности компиляции PHP». - http://jacobsantos.com/2006/general/dont-advocate-subclasses/comment-page-1/

1 голос
/ 29 января 2010

Позвольте мне обратиться к одной важной строке:

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

В PHP для использования инфиксного оператора доступа к объекту (->) левый аргумент должен быть переменной (с добавлением по крайней мере одного $) и должен быть экземпляром класса, например, $myClass->whatever или $this->foo.

Если вы пришли с другого языка и думаете о статическом доступе, вы должны использовать правильный оператор, который является ::, например someClass::$someValue или someClass::SOME_CONST.

Теперь, если вы категорически против передачи «родительского» объекта дочернему конструктору, вы можете рассмотреть шаблон синглтона, который позволит вам статически получить доступ (только) к экземпляру родительского класса из любой точки код, включая дочерний объект.

А если серьезно, просто передайте его в качестве аргумента конструктору, и, как сказал кто-то другой, не определяйте класс внутри функции, особенно если эта функция сама является членом другого класса. Если эта функция вызывается дважды, вы получите фатальную ошибку.

EDIT

Вот пример того, о чем я говорю:

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"
1 голос
/ 29 января 2010

Кажется, вы должны сделать:

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

Итак, извлеките свой внутренний класс из основного класса.

1 голос
/ 29 января 2010

Нет. Когда вы создаете объект как член другого объекта:

$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();
}

это, однако, нечто принципиально отличное от того, что вы делаете сейчас.

0 голосов
/ 30 января 2010

Я нашел больше способов сделать это

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"

это позволяет запускать любые общие функции «экземпляра объекта» из любого общего объекта. теперь основной класс может включать / запускать любой внутренний класс, который он хочет, в то время как внутренний класс имеет возможность запускать функции экземпляра основного класса, как если бы это уже запущенный объект основного класса

0 голосов
/ 29 января 2010

Вы пытаетесь вызывать нестатический метод статически с кодом

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();
  ?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...