使用return语句效果非常好!
当我创建带有返回值的方法时,我通常会尝试进行设置,以便永远不会出现以必须返回某些默认值的方式调用该方法的情况。 当我开始时,我经常会编写执行某些操作的方法,并且返回它们所做的事情,或者如果它们没有执行任何操作,则返回 null。 但我讨厌在我的代码中到处都是丑陋的 if(!null)
语句,
我正在阅读许多个月前由务实的程序员写的关于 ruby 的重新指南,我注意到他们当它们通常不会返回任何内容时,通常会返回 self
(ruby 的 this
)。 他们说,这是为了能够链接方法调用,就像在本例中使用 setter 返回它们设置的属性的对象一样。
tree.setColor(green).setDecor(gaudy).setPractical(false)
起初我觉得这种事情很有吸引力。 有几次我很高兴能够链接方法调用,例如 Player.getHand().getSize() ,但这有些不同,因为方法调用的对象发生了变化一步一步。
Stack Overflow 如何看待返回值? 当您想到返回值时,是否有任何模式或习语会立即浮现在您的脑海中? 有什么好方法可以避免沮丧并增加美丽吗?
When I am making methods with return values, I usually try and set things up so that there is never a case when the method is called in such a way that it would have to return some default value. When I started I would often write methods that did something, and would either return what they did or, if they failed to do anything, would return null. But I hate having ugly if(!null)
statements all over my code,
I'm reading a re-guide to ruby that I read many moons ago, by the pragmatic programmers, and I notice that they often return self
(ruby's this
) when they wouldn't normally return anything. This is, they say, in order to be able to chain method calls, as in this example using setters that return the object whose attributes they set.
tree.setColor(green).setDecor(gaudy).setPractical(false)
Initially I find this sort of thing attractive. There have been a couple of times when I have rejoiced at being able to chain method calls, like Player.getHand().getSize()
but this is somewhat different in that the object of the method call changes from step to step.
What does Stack Overflow think about return values? Are there any patterns or idioms that come to mind warmly when you think of return values? Any great ways to avoid frustration and increase beauty?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
以我的拙见,您应该考虑三种返回情况:
对象属性操作
第一种是对象属性的操作。 您在此处描述的模式在操作对象时经常使用。 一个非常典型的场景就是和工厂一起使用。 考虑这个假设的创建调用:
它允许快速掌握正在创建的内容或如何操作对象,因为这些方法形成了一个人类可读的表达式。 这绝对是好事,但不要过度使用。 经验法则是,这可以与返回值也可以声明为 void 的方法一起使用。
评估对象属性
第二个可能是当方法评估对象上的某些内容时。 例如,考虑方法
car.getCurrentSpeed()
,它可以被解释为发送给对象的消息,询问当前速度并返回该消息。 它只会返回值,不会太复杂。 :)让对象执行这个或那个
第三种可能是当一个方法执行一个操作时,返回某种值来指示调用者的意图的实现程度 - 但是布置这样的方法可能很困难:
这是您可以的地方看到设计该方法的困难。 成功或失败时应该返回 0 吗? 如果无法设置档位,因为汽车只有 5 个档位,那么 -1 怎么样? 这是否意味着当前档位现在也处于-1? 该方法可以返回它更改为的齿轮,这意味着您必须将提供给该方法的参数与返回代码进行比较。 那行得通。 另一方面,您可以简单地返回 true 或 false 表示失败,或者返回 false 或 true 表示失败。 可以通过估计您希望这些方法调用失败还是成功来决定使用哪一个。
以我的愚见,有一种方法可以通过给它们提供语义描述来更好地表达此类返回值的语义。 未来与您的对象交互的开发人员会喜欢您,因为您不必查找方法的注释或文档:
这样,对于任何查看您的代码的程序员来说,返回值的含义都变得非常明显(考虑:
if (gears.changeGear(20) == GearSystem::GearChangeSuccess)
- 这比上面的示例更清楚)反模式:失败作为返回代码。
我实际上省略了返回值的第四种可能性,因为在我看来它不存在:当程序中出现错误时,例如逻辑错误或需要处理的故障 - 理论上您可以返回一个值,表明所以。 但今天,这种情况不再经常发生(或者不应该发生),因为也有例外。
In my humble opinion, there are three kinds of return-cases that you should take into consideration:
Object property manipulation
The first is the manipulation of object properties. The pattern you describe here is very often used when manipulating objects. A very typical scenario is using it together with a factory. Consider this hypothetical creation call:
It allows for a quick grasp at what exactly is being created or how an object is manipulated, because the methods form one human-readable expression. It's definitely nice, but don't overuse. A rule of thumb is that this might be used with methods whose return value you could also declare as void.
Evaluating object properties
The second might be when a method evaluates something on an object. Consider, for example, the method
car.getCurrentSpeed()
, that could be interpreted as a message to an object asking for the current speed and returning that. It would simply return the value, not too complicated. :)Make object do this or that
The third might be when a method makes an perform an operation, returning some sort of value indicating how well the caller's intention was fulfilled - but laying out such a method could be difficult:
This is where you can see a difficulty in designing the method. Should it return 0 upon success or failure? How about -1 if the gear could not be set, because the car only has 5 gears? Does that mean the current gear is at -1 now, too? The method could return the gear it changed to, meaning you would have to compare the argument supplied to the method to the return code. That would work. On the other hand, you could simply return either true or false for failure or false or true for failure. Which one to use could be decided by estimating if you'd expect those method calls to rather fail or succeed.
In my humble opinion, there is a way to better express the semantics of such return values, by giving them a semantic description. Future developers interacting with your objects will love you for not having to look up the comments or documentation for your methods:
That way, it becomes perfectly obvious for any programmer looking at your code, what the return value means (consider:
if (gears.changeGear(20) == GearSystem::GearChangeSuccess)
- much clearer what that means than the example above)Antipattern: Failures as return codes.
The fourth possibility for a return value I actually omitted, because in my opinion it isn't any: when there's an error in your program, like a logic error or a failure that needs to be dealt with - you could theoretically return a value indicating so. But today, that's not done so often anymore (or should not be), because for that, there are exceptions.
我不同意方法永远不应该返回 null。 最明显的例子来自系统编程。 例如,如果有人要求打开一个文件,如果打开失败,您只需给他们 null 即可。 没有明智的选择。 在其他情况下,null 也适用,例如在链表的最后一个节点上调用 getNextNode(node) 方法。 所以我猜这些情况的共同点是 null 代表“无对象”(没有文件句柄或没有列表节点),这是有道理的。
在其他情况下,该方法永远不应该失败,并且有适当的异常设施。 然后,我认为像你的例子这样的方法链接可以发挥很大的作用。 我觉得有点有趣的是,你似乎相信这是“务实的程序员”的创新。 事实上,它可以追溯到 Lisp(如果不是更早的话)。
I don't agree that methods should never return null. The most obvious examples are from systems programming. For instance, if someone asks to open a file, you simply have to give them null if the open fails. There is no sane alternative. There are other cases where null is appropriate, such as a getNextNode(node) method, when called on the last node of a linked list. So I guess what these cases have in common is that null represents "no object" (either no file handle or no list node), which makes sense.
In other cases, the method should never fail, and there is an appropriate exception facility. Then, I think method chaining like your example can be used to great effect. I think it's a bit funny that you seem to believe this is an innovation of the "Pragmatic Programmers". In fact, it dates to Lisp if not before.
返回
this
也用在“构建器模式”中,这是方法链可以增强可读性和编写便利性的另一种情况。null 通常作为带外值返回,以指示无法生成任何结果。 我认为,在没有结果是正常现象的情况下,这是完全合理的; 示例包括在文件末尾从
readLine()
返回 null,或者向get(...)
提供不存在的键时返回 nullMap
的方法。 读取到文件末尾是正常行为(与 IOException 相反,IOException 表示尝试读取时出现异常错误)。 同样,查找某个键并被告知它没有值也是正常情况。在某些情况下,null 的一个很好的替代方案是“null 对象”,它是结果类的完整实例,但对于“无人在家”的情况具有适当的状态和行为。 例如,查找不存在的用户 ID 的结果很可能是一个 NullUser 对象,该对象的名称长度为零,并且没有在系统中执行任何操作的权限。
Returning
this
is also used in the "builder pattern", another case where method chaining can enhance readability as well as writing convenience.A null is often returned as an out-of-band value to indicate that no result could be produced. I believe that this is perfectly reasonable when getting no result is a normal event; examples would include a null return from
readLine()
at end-of-file, or a null returned when providing a non-existent key to theget(...)
method of aMap
. Reading to the end of the file is normal behavior (as opposed to an IOException, which indicates that something went abnormally wrong while trying to read). Similarly, looking up a key and being told that it has no value is a normal case.A good alternative to null for some cases is a "null object", which is a full-fledged instance of the result class, but which has appropriate state and behavior for a "nobody's home" case. For instance, the result of looking up a non-existent user ID might well be a NullUser object which has a zero-length name and no permissions to do anything in the system.
这让我很困惑。 OO编程语言需要Smalltalk的分号:
obj method1; 方法2. 意思是“在 obj 上调用 method1,然后在 obj 上调用 method2”。 这种对象设置很常见。
It's confusing to me. OO programming languages need Smalltalk's semicolon:
obj method1; method2. means "call method1 on obj then method2 on obj". This kind of object setup is very common.