【问题标题】:Calling member function on array调用数组的成员函数
【发布时间】:2018-07-10 10:43:52
【问题描述】:

我并不真正了解链接函数如何处理返回的值。

假设我有一个返回字符串或数组的函数

public static $query; 

public static function getArray($arr) {
     Database::$query = $arr;
     return Database::$query;
}

public function single() {
    return Database::$query[0];
}

为什么,当我调用它时,我可以不将函数链接到它上以影响字符串(在此示例中,我要附加“测试”,我将如何执行此操作?

为什么我不能直接打电话

Database::getArray(array("test","test2"))->single();

没有收到Call to a member function single() on array 错误。但是,让它只返回数组的第一个值。

我将如何去追加做我想要在这里实现的目标?为什么我的逻辑错了?

【问题讨论】:

  • 什么是$query?可能需要查看您的Database 课程
  • 只是一个public static $query;我会添加它!
  • 仅供参考,静态变量基本上是命名空间的全局变量和静态方法 - 命名空间的全局函数。这与 OOP 无关。此外,制作另一个“数据库包装器”是一个非常糟糕的主意。
  • @IMSoP 我见过太多“高级”开发人员,即使经过十年的编程,他们仍然这样写。不向新手指出,他正在做的实际上不是 OOP 并且有更好的方法,这将是一种伤害。

标签: php arrays


【解决方案1】:

当您调用一个方法时,返回值是该方法决定返回的值;返回值与您调用该方法的对象没有任何自动关系。例如:

class A {
    public function foo() {
        return 'Hello, World!';
    }
}
$a = new A;
echo $a->foo();

返回的值只是一个普通的字符串,就像foo 是一个没有附加到任何对象的全局函数。

在 PHP 中,字符串(和其他“基本类型”,如数组)不是对象,因此您不能在它们上调用任何方法。即使可以,这些方法也将内置到语言中,并且您不能仅仅决定可以在任何数组上调用 ->single()

可能令人困惑的是,有些人使用返回对象的约定编写方法,称为“流利的接口”,或更一般地称为“链式方法”。这不是语言的特性,只是从方法返回对象的自然结果:

class A {
    public function foo() {
        return new B;
    }
}
class B {
    public function bar() {
         return 'Hello, World!';
    }
}
$a = new A;
$b = $a->foo(); // $b is a B object
echo $b->bar();
// We can combine this into one line:
echo (new A)->foo()->bar();

这种链接没有什么特别之处;只是只要你有一个对象,你就可以在它上面调用适当的方法,就像你有一个数字一样,你可以用它做数学。与一个简单的加法比较:

function foo() {
    return 1;
}
$a = foo();
$a = $a + 2;
echo $a;
// We can combine this into one line:
echo foo() + 2;
// Or keep the assignment:
$a = foo() + 2;
echo $a;

对象不知道它被链接了 - 事实上,它不需要知道任何关于它周围的代码的信息,这是结构化编程的一个重要部分。

一个常见的模式是有修改方法,它返回他们刚刚修改的对象,所以你可以一次性进行一系列修改:

class A {
     private $words = [];
     public function addWord($word) {
         $this->words[] = $word;
         // $this is the current object, which is an instance of class A
         return $this;
     }
     public function getString() {
         return implode(' ', $this->words);
     }
 }
 $a = new A;
 // Calling $a->addWord(...) gives us back the same object
 $a = $a->addWord('Hello');
 $a = $a->addWord('World');
 // Calling $a->getString() gives us back a string
 echo $a->getString();

 // We can combine this into one line:
 echo (new A)->addWord('Hello')->addWord('World')->getString();

请注意,如果您创建了对象的实例(使用new 关键字),则只能引用$this,而不是在声明为static 的方法中。静态方法仍然可以具有这种模式,但它需要返回一些其他对象,例如 new self(当前类的新实例)或 self::$foo(之前创建的对象)。

【讨论】:

  • 好的,我理解并且有一个返回new self的例子你知道有没有办法检查函数是否被链接?如果函数没有被链接,我想返回一个不同的值。
  • @ConorReid 没有。正如我所说,“链接”不是该语言的特征。写$a = foo(); $a = $a->something();和写$a = foo()->something();完全一样,写$a = 1; $a = $a + 2;和写$a = 1 + 2;一样。
  • @ConorReid 我在答案的中途添加了一个额外的示例,以使这一点更清楚。
【解决方案2】:

它叫做fluent interface,如果你想链接来自同一个类的方法,你必须从每个你想调用fluently的方法中返回this,所以你的代码应该是这样的:

public static $query; 

public function getArray($arr) {
     Database::$query = $arr;
     return $this;
}

public function single() {
    return Database::$query[0];
}

应用更改后,构造 Database::getArray(array("test","test2"))->single(); 将起作用,但是您可以考虑重命名方法 getArray,因为顾名思义,它不应该返回 $this,而是返回数组

@EDIT

您应该将函数 getArray 的类型从 public static function 更改为 public function 以使其工作,您的最终语句也将更改为:

(new Database())->getArray(array("test","test2"))->single();

但是,在这种情况下,我会考虑重新设计您的类并创建某种单例,以便您只实例化一次 Database 类并将对象存储在某处

【讨论】:

  • 如果没有实例可返回,如何返回this
  • @billyonecan 是的,我错过了课堂上的静态函数,更新了答案
  • 如果它不是静态的,我是否需要在我使用它的每个函数中创建一个新的数据库对象,以便它在范围内?看起来很凌乱且不需要。
  • @ConorReid 这就是单例设计的重点——创建一个实例并将其存储在全局某处,然后访问该类的唯一实例,如果你想拥有,这是唯一的方法课堂上流畅的界面
猜你喜欢
  • 2022-11-16
  • 2023-02-06
  • 2021-09-04
  • 2016-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多