你的问题。
但是,但是-出于我的天真,让我尖叫-有时可能会有意义地缺乏价值!
与您一起在船上。但是,我将在一秒钟内说明一些警告。但首先:
空是邪恶的,应尽可能避免。
我认为这是一个很好的想法,但过于笼统。
空不是邪恶。它们不是反模式。这些都不是不惜一切代价避免的事情。但是,空值容易出错(因为无法检查空值)。
但是我不明白如何不检查null是否能以某种方式证明null本质上是错误使用的。
如果null为恶,那么数组索引和C ++指针也是如此。他们不是。他们很容易用脚砸自己,但是不应该不惜一切代价避免它们。
对于此答案的其余部分,我将使“零是邪恶的”的意图适应于更加细微的“ 应负责任地处理零 ”。
您的解决方案。
我同意您的意见,即使用null作为全局规则;在这种特殊情况下,我不同意您使用null的情况。
总结以下反馈:您误解了继承和多态的目的。尽管您使用null的论点具有有效性,但您对另一种方法为何不好的进一步“证明”是建立在滥用继承的基础上的,这使您的观点与null问题无关。
大多数更新自然都会有一个与之相关的玩家-毕竟,有必要知道哪个玩家在此回合中做出了哪个动作。但是,某些更新无法使Player有意义地与它们相关联。
如果这些更新有显着不同(它们是不同的),则您需要两种单独的更新类型。
例如,考虑消息。您有错误消息和IM聊天消息。但是,尽管它们可能包含非常相似的数据(字符串消息和发件人),但它们的行为方式却不同。它们应作为不同的类分别使用。
您现在要执行的操作是根据Player属性的空值有效地区分两种更新。这等效于根据错误代码的存在来确定IM消息和错误消息。它有效,但这不是最佳方法。
- 现在,JS代码将简单地接收不带Player的对象作为已定义的属性,这与它为null相同,因为两种情况都需要检查该值是否存在。
您的论点依赖于多态性的误解。如果你有一个返回的方法GameUpdate
的对象,一般不应该关心过区分GameUpdate
,PlayerGameUpdate
或NewlyDevelopedGameUpdate
。
基类需要具有完全有效的约定,即,其属性是在基类上定义的,而不是在派生类上定义的(也就是说,这些基属性的值当然可以在派生类中被覆盖)。
这使您的论据毫无根据。在良好实践中,您永远不要在乎您的GameUpdate
对象是否具有播放器。如果您尝试访问的Player
属性GameUpdate
,则说明您的操作不合逻辑。
诸如C#之类的类型化语言甚至不允许您尝试访问a的Player
属性,GameUpdate
因为GameUpdate
根本没有该属性。Javascript的方法更为宽松(并且不需要预编译),因此它不会费心去纠正您,而是会在运行时将其炸毁。
- 如果将另一个可为空的字段添加到GameUpdate类中,则我必须能够使用多重继承来继续进行此设计-但是MI本身是邪恶的(根据经验更丰富的程序员),更重要的是,C#不会有它,所以我不能使用它。
您不应基于可空属性的添加来创建类。您应该基于功能上独特的游戏更新类型来创建类。
一般如何避免使用null的问题?
我确实认为,详细阐述如何有意义地表达缺乏价值是很重要的。这是没有特定顺序的解决方案(或不好的方法)的集合。
1.仍然使用null。
这是最简单的方法。但是,您正在注册自己进行大量的空检查,以及(如果不这样做)对空引用异常进行故障排除。
2.使用非空无意义的值
一个简单的例子是indexOf()
:
"abcde".indexOf("b"); // 1
"abcde".indexOf("f"); // -1
相反null
,你得到了-1
。从技术上讲,这是一个有效的整数值。但是,负值是无意义的答案,因为索引应为正整数。
从逻辑上讲,这仅适用于以下情况:返回类型允许的值可能大于有意义返回的值(indexOf =正整数; int =负整数和正整数)
对于引用类型,您仍然可以应用此原理。例如,如果您有一个具有整数ID的实体,则可以返回其ID设置为-1(而不是null)的虚拟对象。
您只需要定义一个“虚拟状态”,就可以通过该状态测量对象是否实际可用。
请注意,如果您不控制字符串值,则不应依赖于预定的字符串值。当您想返回一个空对象时,您可以考虑将用户名设置为“ null”,但是当Christopher Null注册服务时会遇到问题。
3.引发异常。
不就是不。逻辑流不应处理异常。
就是说,在某些情况下,您不想隐藏(nullreference)异常,而是显示适当的异常。例如:
var existingPerson = personRepository.GetById(123);
PersonNotFoundException
如果没有ID为123的人,这可能引发(或类似的)错误。
显然,这仅在以下情况下才可以接受:找不到商品导致无法进行任何进一步处理。如果找不到项目,并且应用程序可以继续,则永远不要抛出异常。我不能太强调这一点。