3

我正在寻找从另一个类调用类方法的最佳方法,而不必使用 Global 来获取类实例,因为我现在明白“全局是邪恶的”!

这里有一些代码来解释它:

class Assets{
 public $assets = array();
 public function add($asset){
  $this->assets[] = $asset;
 }
}

现在我想在这里调用 Assets/call 方法。

$assets = new Assets;
class Form{
 public function __construct(){
  global $assets;
  $assets->add('Form');
 }
}

在这种情况下使用 Global 是不是很糟糕?如果是这样,还有什么其他方式被认为是最好的?

PS:我只需要使用该类的一个实例;意味着我不想在第二个类中创建一个新实例。

4

6 回答 6

7

如果您只想拥有 1 个资产实例,则需要使用某种形式的依赖注入。

在这种情况下,最明显的是通过构造函数传递它:

class Form{
 public function __construct(Assets $assets){
  $assets->add('Form');
 }
}

使用全局变量确实是个坏主意

于 2013-05-28T16:49:44.483 回答
2

如果在您的上下文中有意义,您也可以将 Assets设为单例:

class Assets
{
    /////////////////////
    // Your stuff      //
    /////////////////////

    private $assets = array();
    public function add($asset)
    {
        $this->assets[] = $asset;
    }

    /////////////////////
    // Singleton stuff //
    /////////////////////

    static private $instance = null;
    static public function getInstance()
    {
        if(self::$instance == null)
            self::$instance = new self;
        return self::$instance;
    }

    // To restrict construction of this class outside of this class definition
    private function __construct() {}

    // To restrict cloning of this class outside of this class definition
    private function __clone() {}
}

在您的其他代码中,您将像这样使用单例:

class Form
{
    public function __construct()
    {
        Assets::getInstance()->add('Form');
    }
}
于 2013-05-28T17:17:04.347 回答
1

你可以试试这个

class Form{
 public function __construct(Assets $assets){
  //$assets = new Assets;
  $assets->add('Form');
 }
}
于 2013-05-28T16:46:10.450 回答
1

我没有直接用提供的元素回答这个问题,我只是展示了一种在对象之间共享数据而不使用全局变量的方法。

class A {

    private $v;

    function __construct ($value)
    {
        $this->v = $value;
    }

    function set_v ($value)
    {
        $this->v = $value;
    }

    function print_v ()
    {
        echo $this->v;
    }

}

.

class B {

    private $a;

    function __construct (&$tha)
    {
        if ($tha) {
          $this->a = $tha;
        }
    }

    function print_a ()
    {
        echo $this->a->print_v();
    }
}

.

$mya = new A(12);
$mya->print_v(); // echo 12
$myb = new B($mya);
$mya->set_v(13); 
$myb->print_a(); // echo 13

您可以在另一个对象中保留一个对象的痕迹,并尊重对象的封装。但是,如果 A 的实例被删除,则 B 的实例可能变得不可靠。然后,您应该确保数据在存储它的对象中始终是可靠的(例如,制定一种方法来验证内部数据是否正常)。

此外,正如 tereško 所注意到的,应避免显式等待引用的参数。事实上,从 PHP 5.0 开始,语言中引入了一个新特性,称为类型提示。这可以防止您的程序出现不希望的内存行为,以及可以在编译级别监视任何错误匹配的事实(更多详细信息请参阅类型提示(PHP 官方文档)

因此

function __construct (&$tha) ...

必须重新定义为

function __construct (A $tha) ..

在示例中。

于 2013-05-28T16:50:01.683 回答
1

依赖注入是要走的路。我将使用这个 Factory mechanize 将对象实例传递给另一个对象。如(只是一个样本,没有测试它):

class UI{

public $somthing = 'Cool';

public function newComponent($name){
    return new $name($this);
}

}

$ui = new UI;
class Form{
    public $ui;

    public function __construct(UI $ui){
        $this->ui = $ui;
    }

    public function say(){
        print $this->ui->somthing;
    }
}

$form = $ui->newComponent('Form');

$form->say(); // print 'Cool'.
于 2013-05-28T21:37:03.573 回答
-1

关于什么

<?php
class Assets
{
    protected static $assets = array();

    protected function add($el)
    {
        self::$assets[] = $el;
    }

    public function getAssets()
    {
        return self::$assets;
    }
}

class Form extends Assets
{
    public function __construct()
    {
        parent::add('Form');
    }
}

class Css extends Assets
{
    public function __construct()
    {
        parent::add('Style');
    }
}

$assets = new Assets;
new Form;
new Css;
var_dump($assets->getAssets()); // Prints: array(2) { [0]=> string(4) "Form" [1]=> string(5) "Style" }
于 2013-05-28T17:19:41.550 回答