(delphi11最新学习资料) Object Pascal 学习笔记---第10章第1节( 为TDate类添加属性)

10.1.5 为TDate类添加属性

​ 在第7章,我创建了TDate类,我们现在使用属性来扩展这个类。本章DateProperties这个新的例子,基本上是第七章ViewDate这个例子的扩展。这里是这个类新的定义,有了一些新的方法(用于设置和获取属性的值)以及四个属性。

type
	TDate = class
	private
		FDate: TDateTime;
		function GetYear: Integer;
		procedure SetYear(const Value: Integer);
		function GetDay: Integer;
		procedure SetDay(const Value: Integer);
		function GetMonth: Integer;
		procedure SetMonth(const Value: Integer);
	public
		constructor Create; overload;
		constructor Create(Y, M, D: Integer); overload;
		procedure SetValue(Y, M, D: Integer); overload;
		procedure SetValue(NewDate: TDateTime); overload;
		function LeapYear: Boolean;
		procedure Increase(NumberOfDays: Integer = 1);
		procedure Decrease(NumberOfDays: Integer = 1);
		function GetText: string; virtual;
		property Day: Integer read GetDay write SetDay;
		property Month: Integer read GetMonth write SetMonth;
		property Year: Integer read GetYear write SetYear;
		property Text: string read GetText;
	end;

​ Year,Day和Month属性使用其对应的方法读取和写入各自的值。这里是支持Month属性所需要方法的实现:

function TDate.GetMonth: Integer;
var
	Y, M, D: Word;
begin
	DecodeDate(FDate, Y, M, D);
	Result := M;
end;

procedure TDate.SetMonth(const Value: Integer);
begin
	if (Value < 1) or (Value > 12) then
		raise EDateOutOfRange.Create('Invalid month');
		SetValue (Value, Day, Year);
end;

​ 调用SetValue执行实际的日期编码,在出错的情况下抛出一个自定义异常。我定义的这个异常类对象在日期超出范围时抛出:

type
	EDateOutOfRange = class(Exception);

​ 第四个属性Text仅映射到一个read方法。这个函数声明为虚函数,因为它将在TNewDate这个子类中被取代。一个属性的Get或者Set方法没有理由不使用延迟绑定(第八章大篇幅解释过的功能)。

注意: 在这个例子中,重要的是要知道属性并没有直接映射到数据。属性是对存储在不同类型的信息和不同类型的结构进行简单的计算得来。

​ 在用属性更新了类的实现以后,我们现在是时候更新使用属性的例子了。例如,我们能够直接使用Text属性,并且我们能够提供三个编辑框让用户读取或者写入三个主要属性的值。这实际上是btnRead按钮按下时所要做的:

procedure TDateForm.BtnReadClick(Sender: TObject);
begin
	EditYear.Text := TheDay.Year.ToString;
	EditMonth.Text := TheDay.Month.ToString;
	EditDay.Text := TheDay.Day.ToString;
end;

​ btnWrite按钮做相反的操作,你能够按照两种之一编写代码:

// Direct use of properties
TheDay.Year := EditYear.Text.ToInteger;
TheDay.Month := EditMonth.Text.ToInteger;
TheDay.Day := EditDay.Text.ToInteger;

// Update all values at once
TheDay.SetValue(EditMonth.Text.ToInteger,
EditDay.Text.ToInteger,
EditYear.Text.ToInteger);

​ 这两种方式的不同取决于输入值无效时发生了什么。当我们单独设置每个值的时候,程序可能刚改变了年的值然后就发生了异常,后续的代码被跳过,导致日期仅仅是被部分修改。当我们一次设定所有的值时,要么这些值是正确的并都被设置,要么这些值是无效的,data对象依然是保留了原来的值。实际上,这就是为什么这三个属性应该设置成只读属性的原因,也就是说要保持数据的完整性。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值