關於 TSpsistent中 Assign方法及 AssignTo方法的說明

來源:互聯網
上載者:User

前幾天做試著做了一個很簡單的控制項(是按 d5 開發人員指南來做的)
這個控制項用到了一個從 TPersistent 繼承下來的類

type
    TSomeObject = class(TPersistent)
    private
      FProp1:integer;
      FProp2:string;
    public
      procedure Assign(source:TPersistent);override;
    published
      property  Prop1:integer read FProp1 write FProp1;
      property  Prop2:string read FProp2 write FProp2;
    end;

.
.
.
.

procedure TSomeObject.Assign(source:TPersistent);
begin
  if source is TSomeObject then
  begin
     self.FProp1:=TSomeObject(source).FProp1;
     self.FProp2:=TSomeObject(source).FProp2;
       
  end;
  inherited assign(source);
end;

按 d5中的例子打的,發現一用到 Assign 時總會提示 TSomeObject can not Assing To TSomeObject  這是

怎麼回事呢?為什麼會出現這個錯誤,看了看 TPersistent 別的衍生類別也是這樣實現的呀,都 inherited

Assign(source); 我的怎麼會錯呢?後來試著加了一個 exit;

procedure TSomeObject.Assign(source:TPersistent);
begin
  if source is TSomeObject then
  begin
     self.FProp1:=TSomeObject(source).FProp1;
     self.FProp2:=TSomeObject(source).FProp2;
     exit;  
  end;
  inherited assign(source);
end;

錯誤沒了,為什麼 inherited assign(source) 會出錯呢?於是查看源碼終於找到答案

由於 TPersistent 中的 assign 是一個virtual 方法,沒有具體的實現

<-----  TPersistent 中的源碼  ------>

              procedure TPersistent.Assign(Source: TPersistent);
              begin
                if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
              end;

              procedure TPersistent.AssignError(Source: TPersistent);
              var
                SourceName: string;
              begin
                if Source <> nil then
                  SourceName := Source.ClassName else
                  SourceName := 'nil';
                raise EConvertError.CreateResFmt(@SAssignError, [SourceName, ClassName]);
              end;

              procedure TPersistent.AssignTo(Dest: TPersistent);
              begin
                Dest.AssignError(Self);
              end;

<----------------------------------->

從源碼中可以看到

Assign  ->  AssignTo -> AssignError

不管 是 assign 還是 assignTo 最終要執行  AssignError 方法,所以這就要求繼承自 TPersistent 的類要覆

蓋 TPersistent 的 Assign 方法

<-----  TCollection  ----->

procedure TCollection.Assign(Source: TPersistent);
var
  I: Integer;
begin
  if Source is TCollection then
  begin
    BeginUpdate;
    try
      Clear;
      for I := 0 to TCollection(Source).Count - 1 do
        Add.Assign(TCollection(Source).Items[I]);
    finally
      EndUpdate;
    end;
    Exit;
    //  這裡用到了 exit
  end;
  inherited Assign(Source);
end;

<------------------------->
 
同樣 TStrings  類也是

<-----  TStrings  ----->

procedure TStrings.Assign(Source: TPersistent);
begin
  if Source is TStrings then
  begin
    BeginUpdate;
    try
      Clear;
      FDefined := TStrings(Source).FDefined;
      FQuoteChar := TStrings(Source).FQuoteChar;
      FDelimiter := TStrings(Source).FDelimiter;
      AddStrings(TStrings(Source));
    finally
      EndUpdate;
    end;
    Exit;
    // 同樣這裡也是 exit
  end;
  inherited Assign(Source);
end;

<---------------------->

通過以上可以看出 TPersistent 的衍生類別在覆蓋 Assign 時,滿足條件的的處理過程完成後要退出處理過程

,不要去 inherited Assign(source) , 因為這樣最終會執行到 AssignError

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.