Php 理解传递对象/值时的OOP原则
我不是在OOP中摸索一些东西,我将使用对SO的虚构理解,看看我是否能得到帮助理解 所以,在这一页我们有一个问题。你可以对这个问题发表评论。也有答案。你可以对答案发表评论Php 理解传递对象/值时的OOP原则,php,oop,Php,Oop,我不是在OOP中摸索一些东西,我将使用对SO的虚构理解,看看我是否能得到帮助理解 所以,在这一页我们有一个问题。你可以对这个问题发表评论。也有答案。你可以对答案发表评论 Question - comment - comment - comment Answer -comment Answer -comment -comment -comment Answer -comment -comment 因此,我设想对这种类型的系统(在PHP中,而不是在.Net
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();
问题是:
$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
对象,它知道如何操作数据库中的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();
}
}