承关系的话,图片就会被多次编译进资源中,在我们不知不觉中文件大小可能会翻了几倍。而将图片放在基类窗体中,无论图片被多少个子窗体共用,资源都只被编译一次,因此可以极大的减少生成的可执行文件尺寸和加载速度。
VFI窗体属性及代码重载
VFI支持继承,使我们可以重用一些有共性的代码,但是每个界面又有它特性的一面,这可以通过重载来实现。
比如这回我觉得配置管理窗体上面板的颜色有些单调,想调整为淡黄色的,但是我又不确定其它人是否会赞同我的审美眼光,所以我不打算修改基类的窗体面板颜色属性,而只是修改派生的数据库配置界面上面板的颜色为clInfoback,可以看到我们的派生类窗体上面板的颜色变成了淡黄色,但是基类的面板仍然保持不变,也就是说我在子类窗体中对父类窗体的属性进行了重载。如果修改之后,客户不满意我的颜色搭配,而喜欢基类的颜色搭配,有一个简便的办法可以恢复继承的父类属性,那就是选中面板,然后执行右键菜单中的Revert
to inherited命令就可以了。见下图:
除了属性重载外,Delphi还支持事件重载。接下来,在数据库参数配
置界面上添加一个编辑框,用来指定数据库名,当显示界面的时候,需要在编辑框中给用户展现当前配置的数据库名,因此要在窗体的OnCreate事件中进行编辑框内容的初始化。双击窗体,创建OnCreate事件处理函数,你会发现新建的OnCreate事件不同于普通的OnCreate事件,窗体设计器自动在代码中加了一句Inherited语句,代码示意:
procedure TDBOptionDlg.FormCreate(Sender: TObject);begin inherited; end;
新加的inherited语句调用的其实就是基类的OnCreate事件处理过程。前面基类的OnCreate事件中只是简单的显示一个消息对话框。如果在派生的TDBOptionDlg中不想显示那个愚蠢的消息框,只要把inherited注释掉就可以了。下面是修改后的初始化代码:
procedure TDBOptionDlg.FormCreate(Sender: TObject);begin //inherited; edtDB.Text:='c:\hubdog.db';end;
VFI的局限
在好的技术都有它的局限性,不能包制百病,VFI同样如此。第一个限制就是在派生类的窗体中,我们不能删除从父类继承的组件,同时我们也不能象代码继承那样,使用protected等关键字降低某些界面组件的保护级别,使其对于子类不可见,从这一点上来说VFI不能实现界面元素信息的隐藏,这不符合面向对象的封装要求。那么这就产生一个问题,在某些配置界面中,可能我们不想提供基类界面要求的恢复默认值的操作功能,一个比较丑陋的办法就是修改默认值按钮的visible属性为false。与此相关的一个问题是,如果基类中定义了一个面板,而在派生类中在面板上放了一个按钮,如果修改基类界面时将面板删除的话,则派生类中的按钮也将被删除,这类
问题处理不好的话,有时会产生很大的混乱。
另外,虽然VFI允许重载属性和事件,这就会产生另外一个问题,平时很多人习惯了使用事件来实现界面初始化,响应按钮点击实现参数配置更新等操作。但是由于VFI默认情况会调用基类继承的事件,而如果窗体的继承层次很多,并且在不同层次上都使用事件处理函数来实现业务逻辑,那么很有可能会出现,在不同继承层次上的事件处理函数实现了互相矛盾的业务处理,比如在继承树的中间的某个界面在初始化时,向界面上某个列表框添加了很多字符串,而后面的派生类界面的作者不清楚这个问题,在初始化时先清空列表框的字符串,然后又添加了一些字符串,这就造成了原来信息的丢失。因此使用VFI的时候,建议继承的层次不要太多,同时尽量使用虚方法来代替事件的使用,对于需要某些强制派生类实现的方法,要用定义纯虚方法。
回到我们的参数配置基