本着精心设计的OO的精神,我所延伸的某个类别已经标志着其中一个领域受到保护.这个班级还慷慨地提供了一个公共二传手,但没有吸气剂.
我正在使用一个基类扩展这个类,而基类又由几个孩子扩展.我如何限制从我的孩子访问受保护的变量,同时仍然可以私下操纵它并公开设置它?
见下面的例子:
public abstract class ThirdPartyClass { protected Map propertyMap; public void setPropertyMap(Map propertyMap){ this.propertyMap= propertyMap; } // Other methods that use propertyMap. } public abstract class MyBaseClass extends ThirdPartyClass{ // Accessor methods for entries in propertyMap. public getFoo(){ propertyMap.get("Foo"); } public getBar(){ propertyMap.get("Bar"); } // etc... } public class OneOfManyChildren extends MyBaseClass { // Should only access propertyMap via methods in MyBaseClass. }
我已经发现我可以通过在MyBaseClass中创建字段private final来撤销访问权限.然而,这也妨碍了使用超级类提供的setter.
我能够通过下面的“聪明”来规避这种限制,但它也会导致维护相同地图的两个副本以及复制每个元素的O(n)操作.
public abstract class MyBaseClass extends ThirdPartyClass{ private final Map propertyMap = new HashMap(); // Revokes access for children. /** Sets parent & grandparent maps. */ @Override public final void setPropertyMap(Map propertyMap){ super.setPropertyMap(propertyMap); this.propertyMap.clear(); this.propertyMap.putAll(propertyMap); } }
有没有更好的方法来实现这一目标?
注意:这只是真实问题的一个示例:如何在不保留多个副本的情况下限制对受保护字段的访问?
注意:我也知道,如果该字段首先是私有的,并且具有受保护的访问者,那么这将是一个非问题.可悲的是,我无法控制.
注意:需要IS-A关系(继承).
注意:这可以轻松应用于任何Collection,DTO或复杂对象.
那些误解这个问题的隐喻:
这类似于祖父母有一个饼干罐,他们可以让所有家庭成员和他们家中的任何其他人(受保护).有孩子的父母进入房子,并且由于他们自己的原因,他们希望防止他们的孩子在恶心的情况下进入饼干罐.相反,孩子应该向父母询问巧克力饼干并看到它神奇地出现;同样是糖饼干或奥利奥.他们永远不需要知道饼干都存放在同一个罐子里,或者甚至还有一个罐子(黑盒子).如果罐子属于父母,如果祖父母可以被说服收起饼干,或者如果祖父母本身不需要访问,那么这可以很容易地实现.如果没有创建和维护两个相同的罐子,那么如何才能限制儿童进入,而父母和儿童则不受阻碍.祖父母?
解决方法
这对你来说可能是不可能的,但如果你可以从ThirdPartyClass派生一个接口并让ThirdPartyClass实现它呢?
然后通过委托私有成员ThirdPartyClassImpl实现接口,使MyBaseClass充当装饰器.
即
public interface ThirdParty ... public class ThirdPartyClass implements ThirdParty public class MyBaseClass implements ThirdParty { private ThirdParty decorated = new ThirdPartyClass(); public class SubclassOne extends MyBaseClass....
等等