接口向下转型,子类方法安全问题
举个栗子,HttpServlet有这么一个方法 service(HttpServletRequest req, HttpServletResponse resp),两个参数类型都是接口;HttpServletRequest是Servlet提供的一个接口,它会有很多实现类,这些类会实现接口方法,也可能会新增自己的方法。service()在处理请求时使用到req,req可以调用接口方法;在开发人员知道req具体的实现类的情况下,祂们可以将req向下转型成实现类,从而调用实现类的特有方法,这样的特有方法并不是每个实现类都有的。
如下方代码,MyRequest则是HttpServletRequest的实现类。下方代码调用service()传入MyRequest实例,该实例会自动向上转型为HttpServletRequest类型。service()中调用MyRequest的getPrivateInfo()。这样编码将导致service()方法与调用方耦合,在改变参数实现类的同时需要改变service()的实现逻辑。所以我们应该杜绝这种向下转型的编码方式,但是仅仅靠编码规范怕是约束不了祂们(滑稽)。我们需要一种方法,禁止调用子类特有方法。
//service()调用
MyRequest myRequest = new MyRequest();
servlet.service(myRequest, myResponse);
public class MyRequest implements HttpServletRequest { MyRequest(){ super(); }; public String getPrivateInfo() { return "";//私密信息 } //以下为接口方法实现 @Override public String getAuthType() { return null; } @Override public Cookie[] getCookies() { return new Cookie[0]; } ... }
service(HttpServletRequest req, HttpServletResponse resp) {
MyRequest myRequest = (MyRequest)req;
myRequest.getPrivateInfo();
}
问题:如何禁止子类特有方法的调用。
改变特有方法的访问范围,protected或者private?特有方法有可能会在类外,甚至是包外调用,所以不行。(这里说的调用是类实例直接调用,不是什么说的向下转型再调用的情况)
方法:借助外观类。代码如下,这时service()调用传入的是RequestFacade实例,通过该实例可以间接调用MyRequest实现的接口方法;而特有方法外观类没有,即使向下转型成RequestFacade也无法调用;RequestFacade类内的request属性又是私有的,无法通过request以原来的手段达到目的。这般如此,总算是遏制了那些歪门邪道,功德无量。
//service()调用 MyRequest myRequest = new MyRequest(); servlet.service(new RequestFacade(myRequest), new ResponseFacade(myResponse));
public class RequestFacade implements HttpServletRequest { private HttpServletRequest request; RequestFacade(HttpServletRequest request) { this.request = request; } //接口方法的实现直接调用构造方法传过来实例的方法 @Override public String getAuthType() { return this.request.getAuthType(); } @Override public Cookie[] getCookies() { return this.request.getCookies(); }
... }