PHP:从另一个对象调用对象方法的最佳方法?
我正在寻找从另一个类调用类方法的最佳方法,而不必使用Global来获取类实例,因为我现在知道“Global是邪恶的” 下面是一些代码来进一步解释:PHP:从另一个对象调用对象方法的最佳方法?,php,oop,Php,Oop,我正在寻找从另一个类调用类方法的最佳方法,而不必使用Global来获取类实例,因为我现在知道“Global是邪恶的” 下面是一些代码来进一步解释: class Assets{ public $assets = array(); public function add($asset){ $this->assets[] = $asset; } } 现在我想从这里调用Assets/call方法 $assets = new Assets; class Form{ public fun
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:我只需要处理类的一个实例;意味着我不想在第二个类中创建新实例。您可以试试这个
class Form{
public function __construct(Assets $assets){
//$assets = new Assets;
$assets->add('Form');
}
}
如果您只想拥有一个资产实例,则需要使用某种形式的依赖项注入 在这种情况下,最明显的是通过构造函数传递它:
class Form{
public function __construct(Assets $assets){
$assets->add('Form');
}
}
使用globals确实是个坏主意。我不是直接用提供的元素来回答这个问题,我只是展示了一种不使用globals在对象之间共享数据的方法
class A {
private $v;
function __construct ($value)
{
$this->v = $value;
}
function set_v ($value)
{
$this->v = $value;
}
function print_v ()
{
echo $this->v;
}
}
您可以在另一个对象中保留一个对象的跟踪,并考虑对象的封装。
但是,如果删除了A的实例,则B的实例可能变得不可靠。然后,您应该确保数据在存储它的对象中始终是可靠的(例如,制作一个方法来验证内部数据是否正常)
同样正如特雷什科所注意到的,应该避免明确等待引用的论点。事实上,自PHP5.0以来,该语言引入了一个称为类型暗示的新特性。这样可以防止程序出现不希望出现的内存行为,并且可以在编译级别监视任何错误匹配(更多详细信息,请参阅)
因此
function __construct (&$tha) ...
必须重新定义为
function __construct (A $tha) ..
在本例中。如果在您的上下文中有意义,您还可以将资产设置为:
类别资产
{
/////////////////////
//你的东西//
/////////////////////
private$assets=array();
公共职能部门增加(资产)
{
$this->assets[]=$asset;
}
/////////////////////
//单件物品//
/////////////////////
静态私有$instance=null;
静态公共函数getInstance()
{
if(self::$instance==null)
self::$instance=新self;
返回self::$instance;
}
//将此类的构造限制在此类定义之外
私有函数_构造(){}
//将此类的克隆限制在此类定义之外
私有函数uu clone(){}
}
在您的其他代码中,您将使用如下单例:
class Form
{
public function __construct()
{
Assets::getInstance()->add('Form');
}
}
那怎么办
<?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" }
依赖项注入是一种方法。我将使用这个工厂机械化将对象实例传递给另一个对象。如(只是一个样本,没有测试):
当然可以,但我只需要处理这个类的一个实例。谢谢。你可以像这样使用构造函数注入,公共函数构造(Assets$Assets);注射无疑是一种方式。将构造隐藏在另一个构造函数中是一种不好的做法,从长远来看,这只会使您的工作更加困难(例如,您发现一个用例,其中相同的资产实例应该从不同的表单实例中使用)是的,这是一种很好的做法。还有一些其他的方法也被认为是“好的”,但是在acedemic OOP设计中,
global
、static
或singleton都被认为是不好的。尽量避免这些问题。@Evert,虽然这比任何其他“答案”都要好得多,但您确实应该避免在构造函数中执行任何计算。这会让测试变成一场噩梦。@Evert你能告诉我其他几种方法吗。谢谢。只是研究依赖注入。这很酷,但单身不被认为是一种不好的做法吗?我认为这总是取决于你想做什么。当考虑到一些相当大的项目(比如开源3D引擎)经常使用单例时,我不会说单例通常是一种不好的做法。由于PHP5.0的发布(2004年左右发布),您不应该通过引用传递对象。它扰乱了refcount并导致泄漏。在任何情况下使用globals都是不好的。即使使用纯过程代码,依赖注入也是“语言提供的标准”解决方案。你只是在OOP方面真的很差。也许有点帮助。@Dewan159我想你是从错误的角度来看待这一点的,当一个人从过程的角度开始深入研究面向对象编程(OOP)和PHP并谈论“实践”时,这是很常见的。你知道为什么global
是“坏的”吗?试着先集中精力。在直截了当地批评语言之前,先发展你对该方法的了解,这样你在寻求帮助时会得到更好的回应。一旦您稍微熟悉了为什么注入很重要(例如,它在Java世界中广泛使用。)@Dewan159我不是在定性地陈述您的问题:)我只是注意到您提供的代码片段表明设计目标是错误的。除了PHP(Python、许多JVM语言、Ruby都有DI的一些变体)之外,您所发现的一个弱点是在许多语言中几乎被普遍接受的编码实践。它是OOP的主干。您倾向于将此模式视为问题,这可能意味着您在编写代码时有一些错误的目标。你提到写一个框架。。。也许我们可以继续聊天?@Dewan159:如果你不希望人们总是传递资产对象,那么就不要强迫他们使用构造函数。提供一个工厂类,您可以将资产实例传递一次,并让工厂始终构造表单类。这与global
有什么不同?
class Form
{
public function __construct()
{
Assets::getInstance()->add('Form');
}
}
<?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" }
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'.