创建属性以存储两个值

时间:2016-12-04 21:54:54

标签: delphi

使用Delphi 10我有两个work_startwork_finish类型的TTime private fWorkStart: TTime; function GetWS: TTime; procedure SetWS(const Value: TTime); Public property WorkStart: TTime read GetWS write SetWS; .... procedure MyClass.SetWS(const Value: TTime); begin fWorkStart := value; mydataset.Edit; mydataset.FieldByName('work_start').AsDateTime := fWorkStart; mydataset.Post; end; function MyClass.GetWS: TTime; begin if mydataset.FieldByName('work_start').IsNull then fWorkStart := encodetime(6,0,0,0) else fWorkStart := mydataset.FieldByName('work_start').AsDateTime; result := fWorkStart; end; 我需要从数据库表中读取和写入所以我为每个人创建一个属性,就像那样

full

WorkFinish属性是一样的。那么有两种方法可以创建一个属性,或者我的代码很好吗?

3 个答案:

答案 0 :(得分:4)

Craig's answer演示了记录属性,这意味着您将一个属性设置为一个单元;您无法独立设置开始和结束时间。 Dawood's answer演示了一个数组属性,它允许独立访问,但在使用者身上施加了繁琐的括号表示法。 Kobik's comment改进了语义,但我们可以使用index specifiers做得更好。

首先,定义一个枚举来表示两种情况:

type
  TWorkTime = (wtStart, wtFinish);

在属性声明中使用这些值,并为属性访问器提供一个额外的参数来表示索引:

private
  FWorkTime: :array[TWorkTime] of TTime;
  function GetWT(Index: TWorkTime): TTime;
  procedure SetWT(Index: TWorkTime; const Value: TTime);
public 
  property WorkStart: TTime index wsStart read GetWT write SetWT;
  property WorkFinish: TTime index wsFinish read GetWT write SetWT;

要减少访问者中的the bloat Craig warns about,可以使用相应的字段名称定义另一个数组,这样可以避免为不同的字段重复代码:

const
  FieldNames: array[TWorkTime] of string = (
    'work_start',
    'work_finish'
  );

function MyClass.GetWT(Index: TWorkTime): TTime;
begin
  if mydataset.FieldByName(FieldName[Index]).IsNull then
    FWorkTime[Index] := EncodeTime(6, 0, 0, 0)
  else
    FWorkTime[Index] := mydataset.FieldByName(FieldNames[Index]).AsDateTime;
  Result := FWorkTime[Index];
end;

答案 1 :(得分:1)

有可能:

//Define a record to hold both
type
  TTimeRange = record
    StartTime: TTime;
    EndTime: TTime;
  end;

//And have your property use the record
property WorkHours: TTimeRange read GetWorkHours write SetWorkHours;

但是,这会强制您的类的客户端使用记录结构进行交互。基本上你遇到的并发症超过了你获得的小益处。

所以我不推荐它 (虽然它值得记住这项技术,因为在其他情况下它可能会更有用。)

至于你的代码:

  • 处理物业很好。虽然在您提供的代码中fWorkStart是多余的。
  • 我要警告你的财产作者中的EditPost。除了在Db中一次更新1个字段效率非常低的事实之外,您的方法具有意想不到的副作用。 (你能不能总是假设编辑是正确的选择而不是插入?)
  • 在您的属性阅读器中,假设NULL == 6:00不是一个好主意。 NULL具有非常特定的含义,即该值未知/未分配。在错误的地方默认它导致无法区分6:00和NULL之间的区别。 (我不是说永远不会默认为null;只是理解其含义。)

答案 2 :(得分:1)

是的,您可以使用索引属性

property WorkTime[IsStart: Boolean]: TDataTime read GetWorkTime write SetWorkTime;

  procedure MyClass.SetWorkTime(IsStart: Boolean;const value: TDataTime);
begin
  mydataset.Edit;
  if IsStart then
    mydataset.FieldByName('work_start').AsDateTime := value else
    mydataset.FieldByName('work_Finish').AsDateTime := value;
  mydataset.Post;
end;

function MyClass.GetWorkTime(IsStart: Boolean): TTime;
begin
  if IsStart then
    Begin
      if mydataset.FieldByName('work_start').IsNull then
        fWorkStart := encodetime(6,0,0,0)
      else
       fWorkStart := mydataset.FieldByName('work_start').AsDateTime;
       result := fWorkStart;
    end else
    begin
      if mydataset.FieldByName('work_finish').IsNull then
        fWorkfinish := encodetime(6,0,0,0)
      else
       fWorkfinish := mydataset.FieldByName('work_finish').AsDateTime;
       result := fWorkfinish;
    end
end;