反着直接操作容器的属性,在设计上也不是不可以。比如intrusive list,甚至成员就是容器,每个成员销毁的时候会自动把自己前后接起来。
但是不能搞成题目这样裸奔,要特化、限制。比如写个PackageItem类型,专门用于被放入包裹、析构时自动执行出包裹操作,然后药水继承它、装备继承它,等等。
这是教科书级别的错误示范。
写出这种代码的人,甚至可以连最基本的OOP素养都没有,说的不好听一点儿,这人适不适合写代码都很难说。
正确的做法当然是vczh说的那样。
Item可以有Destory方法,但内部应当是长这样:
packer?.Remove( this );
基本上这种垃圾代码可以说是把代码编写的原则从头到尾的违反了一个遍,从最根本上来说,高内聚和松耦合的原则都违背了,更不用说OOP的SOLID可以从头到尾全部都违背了。
写出这种代码的确是教科书级别的灾难。
在实操中来说,显而易见的问题就是weight被public,这显然带来极大的隐患,而这显然是得不偿失的,weight几乎必须是private set,这样重要的属性竟然公开给外界随意修改,这个类型的健壮性完全为零。任何对weight的不正确操作都可能带来灾难性的后果。
其次,直接对weight进行数值的修改显然是有线程安全问题的。这个问题在代码合乎规范的情况下,对weight的操作只会出现在Add/Remove或者类似的操作中,可以非常方便的集中处理。而在这种教科书级别的错误代码中,weight的操作可能出现在任何地方。也就是说,其实,压根儿没法重构和修复弥补。
恕我直言,写出这种代码的人,压根儿不会写程序。
有人说这只是紧耦的问题未免太搞笑……
weight都public了,问题仅仅只是Packer和Item的紧耦?
只有在Item是Packer的内部类或者友元类,并且weight是private的时候,我们才能说这不过是导致Packer和Item紧耦合在一起了而已,可以权衡得失利弊。
没有什么原则是不可违背的,所有的问题都需要根据具体的场景进行权衡。这个代码的关键问题不在于紧耦,而在于权衡的思路从根本上是错的,几乎没有任何场景可以支持这种写法。因为无论从哪一方面来分析,把weight公开出来都是非常严重的灾难性问题,而带来的好处则几乎看不到……
weight明显是一个计算冗余,公开set必然造成数据不一致的隐患。而且从生命周期来说,Packer是一个长生命周期对象。长生命周期对象的重要字段无任何保护措施的进行set,还存在线程安全和数据不一致的潜在可能,这种代码并没有任何价值,只会埋下无穷尽的隐患。