Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 理解传递对象/值时的OOP原则_Php_Oop - Fatal编程技术网

Php 理解传递对象/值时的OOP原则

Php 理解传递对象/值时的OOP原则,php,oop,Php,Oop,我不是在OOP中摸索一些东西,我将使用对SO的虚构理解,看看我是否能得到帮助理解 所以,在这一页我们有一个问题。你可以对这个问题发表评论。也有答案。你可以对答案发表评论 Question - comment - comment - comment Answer -comment Answer -comment -comment -comment Answer -comment -comment 因此,我设想对这种类型的系统(在PHP中,而不是在.Net

我不是在OOP中摸索一些东西,我将使用对SO的虚构理解,看看我是否能得到帮助理解

所以,在这一页我们有一个问题。你可以对这个问题发表评论。也有答案。你可以对答案发表评论

Question
 - comment
 - comment
 - comment

 Answer
  -comment

 Answer
  -comment
  -comment
  -comment

 Answer
  -comment
  -comment
因此,我设想对这种类型的系统(在PHP中,而不是在.Net中,因为我还不熟悉.Net)有一个非常高的理解,如下所示:

$question = new Question;
$question->load($this_question_id); // from the URL probably
echo $question->getTitle();
要加载答案,我想是这样的(“A”):

或者,你会这样做(“B”):

我想我的问题是,我不知道什么时候或者是否应该传入整个对象,以及什么时候应该传入一个值。传入整个对象给了我很大的灵活性,但我猜它的内存更多,并且容易更改(比如属性或方法重命名)。如果“A”样式更好,为什么不使用函数呢?OOP在这里似乎毫无意义

谢谢,
汉斯

为什么也不及格?那么:

<?php
$question = new Question($id);
$comments = $question->getComments();
$answers = $question->getAnswers();

echo $question->getTitle();
echo $question->getText();

foreach ($comments as $comment)
    echo $comments->getText();

foreach ($answers as $answer)
{
    $answer_comments = $answer->getComments();
    echo $answer->getText();

    foreach ($answer_comments as $comment)
        echo $comment->getText();
}

编辑:可能子模型(本例中为注释或答案)不需要来自父模型的任何内容,只需要和id来执行db查询。传入整个父对象将是过分的。(另外,PHP在垃圾收集对象时使用循环引用的时间非常糟糕,这在5.3系列中可能会得到修复。)

这两种样式都是可以接受的。有时您只需要值,有时您需要对象。在这个例子中,我个人会按照你的第一个例子做一些事情,但是像这样的琐碎程序在野外并不经常存在,所以也许你想要第二个


我的经验法则是用最少的行数来做这件事,这仍然清楚地表明你正试图对你之后的任何人做什么。大多数对象创建与价值传递的开销在现代arch上可能永远都不需要处理。

除了@jasonbar已经提到的内容之外:

我不知道何时或是否应该传入整个对象,以及何时应该传入一个值

这取决于你需要什么和你想要什么

传入整个对象给了我很大的灵活性,但它的内存更多,并且容易更改


当您将对象用作函数的参数时,PHP不会复制该对象。大多数其他语言也一样(默认情况下,如C#和Java,或者根据明确的请求,如C和C++)

虽然我喜欢Jason的答案,但严格来说,它不是OO

$question = new Question($id);
$comments = $question->getComments();
$answers = $question->getAnswers();

echo $question->getTitle();
echo $question->getText();

foreach ($comments as $comment)
    echo $comments->getText();
问题是:

  • 没有信息隐藏,这是面向对象的基本原则
  • 如果答案的格式需要更改,则必须在与存放数据的对象不关联的位置进行更改
  • 该解决方案不可扩展。(没有可继承的行为。)
  • 您必须使行为(紧密耦合)与数据保持一致。否则你就不是在写OO

    $question = new Question($id);
    $questionView = new QuestionView( $question );
    
    $questionView->displayComments();
    $questionView->displayAnswers();
    
    信息的显示方式现在是一个实现细节,并且是可重用的

    请注意,这将打开以下可能性:

    $question = new Question( $id );
    $questionView = new QuestionView( $question );
    $questionView->setPrinterFriendly();
    
    $questionView->displayComments();
    $questionView->displayAnswers();
    
    现在您可以从代码库中的单个位置更改问题的格式。您可以支持注释和答案的多种格式,而无需调用代码(a);(b)需要改变(到很大程度)

    如果因为误用访问器方法而在多个位置编码文本格式细节,那么任何未来的维护人员的生活都将是悲惨的。如果维护者是一个知道你住在哪里的精神病患者,你就会有麻烦

    对象、数据和视图 据我所知,问题出在这里:

    Database -> Object -> Display Content
    
    您希望保持对象的行为以对象固有的逻辑为中心。换句话说,您不希望对象必须做与其核心职责无关的事情。这通常包括加载、保存和打印功能。您希望将它们与对象本身分开,因为如果必须更改数据库或输出格式,您希望在系统中进行尽可能少的更改,并抑制连锁反应

    为了简化这一点,让我们来看看只加载<代码>注释< /代码>;所有内容都适用于

    问题
    答案

    评论类

    Comment类可能提供以下行为:

    • 答复:
    • 删除
    • 更新(需要权限)
    • 还原(从删除)
    • 等等
    CommentDB类

    我们可以创建一个
    CommentDB
    对象,它知道如何操作数据库中的
    Comment
    s。
    CommentDB
    对象具有以下行为:

    • 创造
    • 装载
    • 拯救
    • 更新
    • 删除
    • 恢复
    请注意,这些行为可能在所有对象中都很常见,因此可以进行重构。这还可以让您非常轻松地更改数据库,因为连接信息将被隔离到单个类(所有数据库对象的祖父)

    用法示例:

      $commentDb = new CommentDB();
      $comment = $commentDb->create();
    
    后来:

      $comment->update( "new text" );
    
    请注意,有许多可能的方法可以实现这一点,但您始终可以在不违反封装和信息隐藏的情况下实现这一点

    CommentView类

    最后,
    CommentView
    类将与
    Comment
    类紧密耦合。它可以通过访问器获取
    Comment
    类的属性。信息仍然对系统的其余部分隐藏。
    Comment
    及其
    CommentView
    紧密耦合。其思想是格式保存在一个地方,而不是分散在需要随意使用数据的类中

    任何需要显示注释的类,但形式略有不同
    Database -> Object -> Display Content
    
      $commentDb = new CommentDB();
      $comment = $commentDb->create();
    
      $comment->update( "new text" );
    
    $q = QuestionMapper::get( $questionid );
    
    // here we could either (a) just return a list of Answers 
    // previously eagerly-loaded by the
    // QuestionMapper, or (b) lazy load the answers by 
    // calling AnswerMapper::getByQuestionID( $this->id ) or similar.
    $aAnswers = $q->getAnswers();
    foreach($aAnswers as $oAnswer){
        echo $oAnswer->getText();
    
        $aComments = $oAnswer->getComments();
        foreach($aComments as $oComment){
            echo $oComment->getText();
        }
    }