修饰符(接口篇)

1.无修饰符----传指针,指针被复制一份入栈。函数内修改属性值后,仅仅是修改堆中数据的值,并没有复制堆中的数据,这点与string不同,留意。

 

2.const 修饰符---传指针,指针被复制一份入栈。与无修饰符一致,据说加上const编译器会优化。可加可不加!!

 

3.var修饰符-----直接把变量现在的内存编号传过去,就是说没有任何新指针或其它【入栈】。

 

4.out修饰符----------与var一样,传递过来的是现在变量本身。但是会忽略变量原来的值,就是说变量的指针这个时候是个空指针,不指向任何堆中的数据。

这点与out修饰类不同,会把指针当成一个空指针。

 

 

接下来 我们实验下,不初始化IP的情况。

unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm4 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  /// <summary>
  /// 定义一个接口
  /// </summary>
  IPerson = interface(iinterface)
    //接口方法
    procedure makeLove();
    //接口属性
    function GetName : string;
    procedure SetName(val : string);
    property name: string read GetName write Setname;
    function Getage : Integer;
    procedure Setage(val : Integer);
    property age: Integer read Getage write Setage;
  end;

  /// <summary>
  /// 接口的实现类
  /// 类实现的是接口的读写方法, 属性还是属于接口的; 类可以提供一个储存属性的字段
  /// </summary>
  TPerson = class(TInterfacedObject, IPerson)
    private
      Fname: string;
      Fage: Integer;
    public
      procedure makeLove();
      function GetName : string;
      procedure SetName(val : string);
      function Getage : Integer;
      procedure Setage(val : Integer);
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure abc1(ap: IPerson);
begin
  ap.name := '李大嘴1';
end;

procedure abc2(const ap: IPerson);
begin
  ap.name := '李大嘴2';
end;

procedure abc3(var ap: IPerson);
begin
  ap.name := '李大嘴3';
end;

procedure abc4(out ap: IPerson);
var
  a: string;
begin
  //这句会报错,因为out修饰接口的话,ap进来是入栈一个null指针,会忽略原来堆中的内存,
  //当成一个不指向,任何堆中地址的指针.
  //a := ap.name;
  ap := TPerson.Create;{再这里重新再堆中开辟内存空间}
  ap.name := 'wokao';
end;

procedure TForm4.Button1Click(Sender: TObject);
var
  ip: IPerson;
begin
  //如果是out修饰符的话,其实这里可以不初始化,因为即使你初始化了也会被忽略.
//  ip := TPerson.Create;
//  ip.name := '小李飞刀';
//  ip.age := 29;

  abc4(ip);
  Memo1.Lines.Add(ip.name);

  //接口不需要释放,指针出栈后,引用计数自动减少,堆中数据自动销毁.
  //ip.Free;
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown := True;
end;

{ TPerson }

function TPerson.Getage: Integer;
begin
  Result := Self.Fage;
end;

function TPerson.GetName: string;
begin
  Result := Self.Fname;
end;

procedure TPerson.makeLove;
begin

end;

procedure TPerson.Setage(val: Integer);
begin
  Self.Fage := val;
end;

procedure TPerson.SetName(val: string);
begin
  Self.Fname := val;
end;

end.
原文地址:https://www.cnblogs.com/del88/p/6672049.html