猿问

方法链接-为什么它是一个好习惯?

方法链接是对象方法返回对象本身以使结果被另一个方法调用的实践。像这样:


participant.addSchedule(events[1]).addSchedule(events[2]).setStatus('attending').save()

这似乎被认为是一种好习惯,因为它会产生可读的代码或“流畅的界面”。但是,对我而言,它似乎打破了面向对象本身所隐含的对象调用表示法-生成的代码不代表对先前方法的结果执行的动作,通常这是面向对象的代码的工作方式:


participant.getSchedule('monday').saveTo('monnday.file')

这种差异设法为“调用结果对象”的点标记创建了两种不同的含义:在链接的上下文中,以上示例将被视为保存参与者对象,即使该示例实际上旨在保存计划表也是如此。 getSchedule接收的对象。


我知道这里的区别在于是否应期望被调用方法返回某些内容(在这种情况下,它将返回被调用对象本身进行链接)。但是,这两种情况与符号本身并没有区别,仅与被调用方法的语义相区分。当不使用方法链接时,我总能知道方法调用是在与上次调用的结果相关的操作上进行的-通过链接,这种假设会中断,我必须在语义上处理整个链,以了解实际对象是什么叫真的是。例如:


participant.attend(event).setNotifications('silent').getSocialStream('twitter').postStatus('Joining '+event.name).follow(event.getSocialId('twitter'))

在这里,最后两个方法调用引用getSocialStream的结果,而之前的方法引用参与者。实际在上下文发生变化的地方写链可能不是一个好习惯(是吗?),但是即使如此,您也必须不断检查看起来相似的点链实际上是否在同一个上下文中,或者只在结果上起作用。


在我看来,虽然表面上的方法链接确实会产生可读的代码,但是点符号含义的重载只会导致更多的混乱。由于我不认为自己是编程专家,所以我认为这是我的错。所以:我想念什么?我是否理解方法链接有些错误?在某些情况下方法链接特别好还是在某些情况下特别糟糕?


旁注:我知道这个问题可以理解为掩盖为问题的意见陈述。但是,它不是-我真正地想理解为什么链接被认为是一种好习惯,而在认为链接破坏了固有的面向对象表示法的地方我犯了错。


冉冉说
浏览 511回答 3
3回答

斯蒂芬大帝

我同意这是主观的。在大多数情况下,我避免使用方法链,但是最近我还发现了一种情况,那就是正确的做法-我有一个方法可以接受10个参数之类的参数,并且需要更多的参数,但是在大多数情况下,您只需要指定一个很少。使用覆盖时,这变得非常麻烦。相反,我选择了链接方法:MyObject.Start()    .SpecifySomeParameter(asdasd)    .SpecifySomeOtherParameter(asdasd)    .Execute();这有点像工厂模式。方法链接方法是可选的,但是它使编写代码更容易(尤其是使用IntelliSense)。请注意,这只是一个孤立的案例,并不是我的代码中的常规做法。关键是-在99%的情况下,无需方法链接就可以做得甚至更好。但这是1%的最佳方法。

犯罪嫌疑人X

只是我的2美分;方法链接使调试变得棘手:-您不能将断点放在简明的位置,因此您可以将程序恰好停在所需的位置-如果这些方法之一引发异常,并且您获得了行号,则不知道“链”中的哪种方法引起了问题。我认为通常最好写短而简洁的行。每行应该只进行一个方法调用。优先选择更多行而不是更长行。编辑:评论提到方法链接和换行符是分开的。那是真实的。但是,取决于调试器,可能在断点中间放置断点,也可能不断点。即使可以,使用带有中间变量的单独的行也可以为您提供更大的灵活性,并提供大量值,您可以在“监视”窗口中检查这些值,以帮助调试过程。

阿晨1998

就个人而言,我更喜欢只对原始对象起作用的链接方法,例如设置多个属性或调用实用程序类型的方法。foo.setHeight(100).setWidth(50).setColor('#ffffff');foo.moveTo(100,100).highlight();当我的示例中一个或多个链接方法将返回foo以外的任何对象时,我不使用它。从语法上讲,只要您为链中的那个对象使用正确的API,就可以链接任何东西,但是更改对象IMHO会使事情变得不那么易读,并且如果不同对象的API有任何相似之处,则可能会造成混乱。如果你做一些非常常见的方法调用末(.toString(),.print(),等等),其对象是你最终作用在?随便阅读代码的人可能不会发现它是链中隐式返回的对象,而不是原始引用。链接不同的对象也可能导致意外的空错误。在我的示例中,假设foo有效,则所有方法调用都是“安全的”(例如,对foo有效)。在OP的示例中:participant.getSchedule('monday').saveTo('monnday.file')...无法保证(作为外部开发人员查看代码)getSchedule实际上会返回有效的非null调度对象。同样,调试这种类型的代码通常要困难得多,因为许多IDE不会在调试时将方法调用评估为可以检查的对象。IMO,任何时候您可能需要检查对象以进行调试时,我都希望将其放在显式变量中。
随时随地看视频慕课网APP
我要回答