7.3.2 封装和窗体
封装的主要理念之一是减少程序中使用的全局变量的数量。全局变量可以从程序的任何部分访问。因此,全局变量的改变会影响整个程序。另一方面,当你更改类字段的表示方法时,只需要修改该类中引用给定字段的某些方法的代码,而不需要修改其他代码。因此,我们可以说信息隐藏涉及封装更改。
让我用一个实际例子来说明这个观点。当你有一个包含多个窗体的程序时,你可以通过在窗体单元的interface部分将某些数据声明为全局变量,从而使每个窗体都可以使用这些数据:
var
Form1: TForm1;
NClicks: Integer;
这种方法可行,但有两个问题。首先,数据(NClicks)不与窗体的特定实例相关联,而是与整个程序关联。如果创建两个相同类型的窗体,它们将共享数据。如果想让同一类型的每个窗体都有自己的数据副本,唯一的解决办法就是将其添加到窗体类中:
type
TForm1 = class(TForm)
public
FNClicks: Integer;
end;
第二个问题是,如果将数据定义为全局变量或窗体的公共字段,那么将来就无法在不影响使用数据的代码的情况下修改其实现。相反,如果只需从其他窗体读取当前值,则可以将数据声明为私有,并提供一个读取该值的方法:
type
TForm1 = class(TForm)
// 这里是组件和事件处理程序
public
function GetClicks: Integer;
private
FNClicks: Integer;
end;
更好的解决方案是在窗体中添加一个属性,我们将在第10章中详细介绍。你可以通过打开ClicksCount
示例来尝试此代码。简而言之,此项目的窗体有两个按钮和顶部的标签,大部分表面留给用户点击(或轻点)。在这种情况下,计数增加,并更新标签以显示新值:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
begin
Inc(FNClicks);
Label1.Text := FNClicks.ToString;
end;
你可以在图7.1中看到应用程序的运行情况。该项目的窗体还有两个按钮,一个用于创建相同类型的新窗体,另一个用于关闭它(这样你可以将焦点返回到以前的窗体)。
这是两种方法的代码:
procedure TForm1.Button1Click(Sender: TObject);
var
NewForm: TForm1;
begin
NewForm := TForm1.Create(Application);
NewForm.Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
图 7.1: ClicksCount 示例的窗体显示了表单上的点击或轻点次数(使用私有窗体数据进行跟踪)