(这是一个类似C的环境)假设我有两个实例对象,一个汽车和一个bodyShop。该车有一个颜色iVar和相应的加速器。 bodyShop有一个名为“paintCar”的方法,它将接收一个汽车对象并改变它的颜色。
就实施而言,为了让bodyShop实际上能够改变汽车对象的颜色,我看到了两种方法。
使用“&”操作员传入指向汽车的指针。然后bodyShop可以告诉汽车执行一些必须改变颜色的方法,或者它可以直接使用汽车的存取器。
按值传递汽车对象,执行相同类型的操作以更改颜色,然后让方法返回具有新颜色的汽车对象。然后将原始汽车对象分配给新的汽车对象。
选项1对我来说似乎更直接,但我想知道它是否符合OOP最佳实践。一般来说,“最大OOP”是“&”运营商好还是坏?或者,也许我完全错过了一个更好的选择,可以使这个超级OOPer。请指教:)
答案 0 :(得分:5)
首选选项1:
bodyShop可以告诉汽车 执行它必须的一些方法 改变颜色,或者它可以使用汽车 访问者直接访问。
更好的是......创建一个IPaintable接口。有车实施IPaintable。让BodyShop依赖于IPaintable而不是Car。这样做的好处是:
答案 1 :(得分:3)
我认为bodyShop的责任是修改汽车对象,所以#1似乎是找我的正确方法。我从未使用过“&”的语言操作员是必要的。通常,我的bodyShop对象会调用car.setColor(newColor),那就是那个。这样您就不必担心原车的其他属性,包括持久性问题 - 您只需将它们留下。
答案 2 :(得分:2)
由于你对最好的OOP练习感兴趣,你应该忽略你用选项2获得的性能。你应该感兴趣的唯一事情就是不必要地增加两个类之间的耦合,是否违反了封装和是保持身份。
鉴于此,选项2不太理想,因为您无法确定哪些其他对象持有对原车的引用,或者更糟,包含汽车。简而言之,您违反了身份约束,因为系统中的两个对象可能对汽车状态有不同的想法。您冒着使整个系统不一致的风险。
当然,您的特定环境可能会避免这种情况,但最好避免使用它。
最后一点,你的bodyShop对象是否有状态;行为和身份?我意识到你只解释了必要的最低限度,但是bodyShop可能并不是真正的对象。
作为一个有趣的方面,选项2将接近功能编程环境中的方法 - 由于不允许状态更改,因此唯一的方法是在颜色发生变化时创建新车。这不是你所建议的,但它很接近。
这可能听起来像完全矫枉过正,但它确实有一些有趣的含义,可以证明代码和并行性的正确性。
答案 3 :(得分:1)
选项1赢了。 &运算符隐含在许多OO语言中(如Java,Python等)。您不经常使用那些语言中的“按值传递” - 只有原始类型以这种方式传递。
选项2带来了多个问题:你可能拥有一系列汽车,而一些不知道它的功能可能会将车送到bodyShop进行喷漆,接收新车以及不更新你的汽车收藏。看到?从更具意识形态的角度来看 - 每次想要在现实世界中修改它时都不会创建新对象 - 为什么要在虚拟世界中进行修改?这会导致混乱,因为它只是违反直觉。 : - )
答案 4 :(得分:1)
我不确定这个“C状环境”是什么意思。在C中,你需要这个:
int paintCar(const bodyShop_t *bs, car_t *car);
修改汽车指向的内容。对于C中的大结构,应始终将指针传递给函数,而不是值。因此,使用解决方案1(如果“&”表示C运算符)。
答案 5 :(得分:0)
我也同意第一个1.我不能说这是最佳实践,因为我从未真正确定在其他人的思想中最佳实践是什么......我可以告诉你,我心中的最佳实践是最适用于工作的简单方法。我也看到过hunspell win api和其他我不得不使用的c-ish api的问题。所以,我同意斯科特的意见。
http://hunspell.sourceforge.net/
//只是你有兴趣查看其他人的代码
答案 6 :(得分:0)
这取决于车身车间的方法是否会失败并使车辆处于不确定状态。在这种情况下,您最好使用汽车副本或汽车所有相关属性的副本。然后,只有在操作成功时,才会将这些值复制到汽车中。因此,您最终会在车身车间方法中将新车分配给旧车。正确地执行此操作对于C ++中的异常安全是必要的,并且可以获得nasty。
使用其他模式也是可能的,有时也是可取的 - 在修改时返回一个新对象。这对于需要撤消/重做,回溯搜索以及任何涉及对象系统如何随时间演变的建模的交互式系统非常有用。
答案 7 :(得分:0)
除了其他意见,选项1让我们绘制Car方法返回一个完成代码,指示汽车是否已成功更改颜色或存在问题