OP于1985年诞生于Apple,后于1995年由Borland公司继承.

DelphiBorland公司的 Anders Hejlsberg 研发,后来他去了Microsoft,开发了C#.

Basic

  • 不区分大小写
  • form init: onCreate --> onShow --> onPaint --> onActive --> onCloseQuery --> onClose.
  • .dfm
    窗体文件,当创建一个窗体时,Delphi5将创建窗体+单元(.pas)一对文件,{$R *.dfm}指示编译器去链接对应的窗体文件.
    可以以文本方式编辑窗体文件,可以看到它主要用于描述窗体中控件的布局、事件等信息.
    编译生成的中间文件: .dcu(Delphi Compiled Unit)Pascal编译的中间结果,只有当源代码不能使用时才需要
  • .res
    包含了应用程序的图标、版本等信息.将自己的资源文件添加到项目中: {$R myResourceFile.res}
  • .dpk
    包文件,编译后会生成.bpl动态链接库文件.bpl由若干个编译单元(.dcu)组成.
  • shortcuts
    F11: 对象观察器、窗体、代码窗口之间的切换
    c + j: 代码补全.
    c + F3: callstack窗口

数据对象

字符串各种对象是引用赋值,但是使用了copy-on-write技术,即➡️
俩引用指向相同的对象时,一个引用改变了则只影响自身,并且引用计数–

其他的数据类型如数组都是引用赋值,一个改变可以影响另一个
深拷贝可以调用copy(arr,index,num)!

基本类型

typeattr
booleanchar, 1B
boolint, 4B
charchar, pchar <–> char*
ansicharchar, ansistring(string). 长度没有限制,\0结尾
widecharshort, widestring, pwidechar <–> wchar_t*
shortintchar
byteunsigned char b = byte(c)
smallintshort
wordunsinged short
integerint
longintlong
int64long long
singlefloat, 4B
doubledouble, 8B
extendlong double, 10B
currency8B
TDateTime8B
variant16B

基本语法

{$if[n]def VER130}
  // Delphi5 specific code
{$else}
{$endif}

V : variant;  // 该种类型会自动减少引用数量
V := 1; V := 'a';
V := CreateOleObject('word.Basic');
i := integer(V);  // 强制转换为整形

p : ^integer;  // int*p,下方var定义时候可以使用pint
p : pointer;   // 一个无类型的指针,void*
new(p);        // 分配内存,注意:不能为pointer+pchar分配,因为不知道要分多少.
p^.mem1 := 1;  // 获得指针所指对象并引用其中的成员mem1
dispose(p);    // 释放内存

f : array[0..8] of integer;  // int f[8],上下界可以任选,使用low(f)+high(f)来获得上下界
g : array[1..2,1..2] of single;  // 多维数组, g[1,2]来访问元素(1,2)
h : array of string;  // 声明一个动态数组,使用前应使用setLength(h,2)先分配内存![0,2)

// 最多256个元素(最好<32),类型必须有序.故integer、string等不能作为类型!
s : set of 'A'..'z';  // 集合类型,可以是'set of <Type>'
s := s + '*';  // 添加一个元素,也可以使用include(s,'*'),使用函数效率高一些;
s := s - '*';  // 减少一个元素,也可以使用exclude(s,'*');
if not ('S' in s) then  // 如果字符'S'没有再集合s中
if {'a','?'} * s = {'a'} then  // 计算交集

if Dog is Animal then Dog(mydog).eat();
mydog := myAnimal as Dog;
unit Foo;  // 单元是程序的源代码模块,必须要和文件名相匹配
uses Foo;  // 使用某个单元

case someIntegerVar of
  101 : doSomething;
  202 : begin  // begin.end.相当于一对{},框定一段代码区域
    end;
  else doTheDefault;
end;

while (x<>y) or (x>=y) do
  if not (a=b) then
    i := 5 div 2;  // 整数除,2
    i := 5 mod 2;  // 取模,1
    dec(i,2);      // i-2
  else if x=2 then
    repeat  // repeat循环
      break;
    until x<2;
  else
    for i:=1 to 8 do  // for循环
      continue;
end;

try
  ...
except
  on ETYPE1 do
    raise...
  on ETYPE2 do
    ...
finally
  ...
end;

// 函数需要返回一个值,过程procedure不能返回!使用exit提前退出过程或函数.
function Foo(var x:longint, s:string='a') : boolean;
var
  a, b : integer;
  s : string;
begin
  setLength(s,1);  // 设置s的大小,初始化
  s := s + 'ok';  {a comment}
  inc(x);  // x++;参数x使用var修饰后可被修改
  result := true;
end;

class

// 定义接口
IA = interface
  ['GUID']  // ctrl+shift+g
  function retFun : integer;
end;

// 定义类,type下方可以定义多个类
type
  TFoo = class(Parent,IA,IB)  // 实现俩接口
  MyRec = record  // type用来定义一个新的名字,record==struct
    I : integer;
    S : string;
  end;
  MyRecFile : file of Myrec;  // 定义一个记录文件
  PMyRec = ^MyRec;
const
  c : integer;  // 只有全局的才支持直接赋值,实际上会默认自动赋值
private
  I : ISomeInterface;
  someValue : integer;
published
  property Value : integer read someValue write virtualFun;  // 对象的暴露属性
end;
public
  constructor Create(y,m,d : integer); override;
  function IA.retFun : integer;  // 继承的接口,如果retFun不歧义也可以不用前缀IA.
  procedure staticFun(I,i:integer;j:TObject);
  procedure staticFun(S:string); reintroduce;  // 不想overrwrite父类的同名同参方法,在子类也引入一个!
  procedure virtualFun; virtual; abstract;
  procedure messageFun; message wm_someMessage;
end;

// 接口的实现
function TFoo.IA.retFun() integer;
begin
  result := 0;
  I := FunctionReturningAnInterface;  // 引用计数自动+1
  I.someFunc;  // 超出作用域后引用计数自动-1
end;