【问题标题】:PHP output result of a class一个类的PHP输出结果
【发布时间】:2016-09-22 06:58:30
【问题描述】:

我经常喜欢让班级来处理整个任务。使用一些参数调用该类,然后获取结果。

我做不到:

<?php
class MyClass{
    function __construct() {
        $this->one = $this->one();
        $this->two = $this->two();
        $this->three = $this->three();

        return $this->three;
    }

    function one() {
        $output = 'One';
        return $output;
    }

    function two() {
        $output = $this->one . 'Two';
        return $output;
    }

    function three() {
        $output = $this->two . 'Three';
        return 'Three' . $this->two;
    }
}

echo new MyClass();

我可以这样做:

<?php
class MyClass{
    function run() {
        $this->one = $this->one();
        $this->two = $this->two();
        $this->three = $this->three();

        return $this->three;
    }

    function one() {
        $output = 'One';
        return $output;
    }

    function two() {
        $output = $this->one . 'Two';
        return $output;
    }

    function three() {
        $output = $this->two . 'Three';
        return 'Three' . $this->two;
    }
}

$obj = new MyClass();
echo $obj->run();

但上述方法真的是正确的方法吗?那么我认为不需要构造。

【问题讨论】:

  • 如果您不需要某些东西 - 不要使用它。

标签: php class constructor


【解决方案1】:

使用类的构造函数的正确方法是让它设置好可以使用的类。在许多情况下,构造函数除了接受依赖项(例如数据库对象)之外并没有做太多事情,并保存这些以供以后使用。
(Ab) 使用您在第一个示例中所做的构造函数会导致许多困难,主要是因为简单地创建对象除了创建所述对象之外还有其他副作用。

以这种方式,您的第二个示例更接近于真正的面向对象编程,即使您仍然没有真正利用使用类为您提供的任何东西。事实上,将其编写为纯过程代码会更好。

虽然我不知道您的代码做了什么,但我尝试了一个示例,利用类的特性为您提供:

    /**
     * We need a DB connection in case we need to get something from the database.
     * This is called a dependency, and we save it in the object at object creation time.
     * 
     * Nothing that causes the object itself to do "work" is supposed to be here, only things
     * necessary for actually creating the object in a state where we can _start_ working with it.
     * 
     * @param PDO $db
     */
    public function __construct (PDO $db) {
        $this->db = $db;
    }

    /**
     * Sets the value for each step. Legal values for $step is between 1 and 3, inclusive.
     * Normally we'd have many setters, one for each property we want to change from outside.
     * That can be anything from address to price and anything else one can think of.
     * 
     * @param int $step
     * @param int|string $value
     * 
     * @throws InvalidArgumentException
     * @return void
     */
    public function set_value ($step, $value) {
        if ($step <= 0 || $step > 3) {
            throw new InvalidArgumentException("Step must be between 1 and 3, inclusive.");
        }

        $this->value[$step] = $value;
    }

    /**
     * This is where the actual processing is done.
     * In a normal class there would be several such functions
     * each doing one specific thing (creating a new record, saving
     * it to the database, validating stuff, etc).
     * 
     * @return void
     */
    public function do_processing () {
        $this->result = implode(", ", $this->data);
    }

    /**
     * Fetches the result of the class. Normally we have many getters, which return
     * one part of the data associated with the object. Such as username, hash, email, etc.
     * 
     * These are often in a 1-1 relationship with setters.
     * 
     * @return string
     */
    public function get_result () {
        // If we have no calculated result, fetch it from the DB instead.
        if (empty($this->result)) {
            return $this->db->get_cached_result ();
        }
        // Returns the newly calculated result.
        // Should probably also cache it, to make the above line useful.
        return $this->result;
    }
}

// A DB interface class, which extends PDO. 
$db = new MyClassDB ();

$obj = new MyClass ($db);
$obj->set_value (2, "Two");
$obj->set_value (1, "One");
$obj->set_value (3, "Three");
$obj->do_processing();
echo $obj->get_result();

请注意,这是一个非常简单的类,并不能很好地帮助您了解如何正确利用类。我建议查看更充实的类,您可以在任何主要框架中找到它。

【讨论】:

  • 这里不需要加一个参数:$obj = new MyClass();将数据库插入到构造中?
  • @JensTörnell:您确实是正确的。谢谢你抓住这个。 :) 我已经更新了我的答案以包含这个。
  • 我想我终于明白如何使用 OOP 了。我想我需要一个基于我自己的代码的非常简短的示例来查看它。十分感谢!不是唠叨,但我也认为$obj-&gt;set_value1 (应该是$obj-&gt;set_value (?我的猜测是您修改了类方法并忘记修改方法调用?
  • 呵呵,不用唠叨了。很高兴人们帮助我发现错误,以便更正它们。 :) 不知道 1 是如何结束的,但是......无论如何,很高兴我能提供帮助。
【解决方案2】:

您可以将您的类方法定义为静态的,然后像 PHP 喜欢说的那样“静态地”调用它们。像这样,

<?php
class MyClass {

private static $one;
private static $two;
private static $three;

public static function run() {
     self::$one = self::one();
     self::$two = self::two();
     self::$three = self::three();

     echo self::$three;
}

private static function one() {
    return 'One';
}

private static function two() {
    return self::$one . 'Two';
}

private static function three() {
    return self::$two . 'Three';
}
}

MyClass::run();

?>

【讨论】:

  • 您也可以将其更改为 return self::$three 并改为调用 echo MyClass::run(),就像在原始示例中一样。
【解决方案3】:

不推荐使用构造函数的返回值。

class MyClass{
    function __construct() {
        $this->one = $this->one();
        $this->two = $this->two();
        $this->three = $this->three();

        echo $this->three;
    }

    function one() {
        $output = 'One';
        return $output;
    }

    function two() {
        $output = $this->one . 'Two';
        return $output;
    }

    function three() {
        $output = $this->two . 'Three';
        return 'Three' . $this->two;
    }
}

new MyClass();

【讨论】:

  • 为什么不应该使用构造函数return
  • 粗略地说,在 OOP 中,构造函数用于在内部初始化对象。他们不应该对外部观察者正确地“做任何事情”,比如返回错误/异常以外的值,或者使用 echo 语句。他们的工作严格来说是新对象的内部工作(例如打开数据库连接或检查文件是否存在等)
  • 我希望 zhenglc 可以编辑他们的答案并添加此信息。
  • 我知道我应该保持安静,哈哈。好的,不要管这部分。
  • @SomeDude 这是有用的 cmets,但我更倾向于让回答者改进他们的答案,仅代码答案不是很有帮助。并且声明不推荐的东西总是会通过一些细节来改进为什么:-)(也就是说,我对这个问题的回答也有点裤子:-/
【解决方案4】:
<?php
class MyClass{
    private $one; //private or public or protected. 
    private $two; //placeholder class variables. 
    private $three;

    function __construct() {   
        $this->run();
    }

    function run(){
        $this->one(); //set value one
        $this->two(); //set value two
        print $this->three(); //set and then output value 3.
    }

    function one() {
        $output = 'One';
        return $output;
    }

    function two() {
        $output = $this->one . 'Two';
        return $output;
    }

    function three() {
        $output = $this->two . 'Three';
        return 'Three' . $this->two;
    }
}

//printed output from run automatically given to output buffer.    
// can't print 'new class' syntax. 
new MyClass(); //outputs result of function three();

重做的类所做的是,变量已被移动为类变量,而不是全部设置在 __construct 中,然后在最后一个被设置之前,这些都与关联的方法一起设置按原件退回。

【讨论】:

  • 1.构造函数不应该用来做工作。 2. __construct() 返回创建的对象,使用return 这里是BAD CODE。老实说,甚至不确定它是否会起作用。在大多数语言中,这要么会导致致命错误,要么会被忽略。 3.这仍然是程序代码,完全浪费了类的使用。
  • @ChristianF 感谢您的澄清;构造函数不能只调用run 方法而不返回,而run 方法返回它自己的值吗? (所以它可以从构造函数中删除返回字,当创建新对象时,run 函数的结果仍然会传递回主脚本?)
  • 完全有可能有一个空的构造函数(或者更确切地说,一开始就不定义它)。在生产代码中看到这种情况并不少见,尤其是在该类没有任何依赖项的情况下。但是,仅通过在包装器方法中一个接一个地链接方法,而不对类做任何其他事情,您仍然只是添加大量代码而没有任何好处。代码本身仍然是程序性的,因此应该在不使用类的情况下编写。有关简单的 OOP 方法,请参阅我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多