类是一种用户自定义的数据类型,可以说它是对某一类事物的抽象描述,类使用属性和方法来描述某一事物的具体特性和行为。
类中所定义的所有数据都是类的成员,类中的定义的属性也可以称为成员变量,类中定义的方法也可以称为类的成员方法。
一般使用 T 作为定义类名的前缀,如下:
//标准语法 TMyClass1 = class(TObject) end; //如果是继承自 TObject 可以省略 TMyClass2 = class end; //可以实现多个接口; 实现接口时经常用到 TInterfacedObject 类, 它实现了接口的默认方法 TMyClass3 = class(TInterfacedObject, Interface1, Interface2) end; //现在 TMyClass4 相当于 TObject 的别名 TMyClass4 = class(TObject); //用 class abstract 说明抽象类, 但内部必须有抽象方法, 才是真正的抽象类. TMyClass5 = class abstract(TObject) procedure Proc; virtual; abstract; end; //用 class sealed 定义不可继承的类 TMyClass6 = class sealed(TObject) //... end; //这是定义了一个 TObject 类型的指针; TMyClass 称作 TObject 的类引用或元类 TMyClass = class of TObject;
对象实际上是类的一个指针类型,新创建的对象地址指向为 nil。所以不能进行任何操作,否则会导致内存报错产生程序异常。
要想使该对象可用,需要使用对象所在类的Create构造函数对其进行初始化。即对象实例化(创建对象),这时对象就会指向一个非空的地址空间。
由于我们说对象是类的指针类型,那在我们定义对象后实际上就是定义了一个类的指针类型。对象定义如下:
var chinese: TPerson;
上方只定义了对象,未创建。指针类型的定义是被分配地址空间的,只有对象创建后才会为对象创建一个地址空间,并初始化类中的所有数据,并进行访问。
当一个类创建了该类的对象,通常称为对象为该类的实例,通过这个对象可以对该类的属性,成员方法进行访问。对这个对象的操作也就是对该类的操作。
如果说类是对客观事物的一种抽象,那么对象就是对这一抽象事物的实现。
对象是类的指针类型,比较对象与指针类型的异同:
1.指针与对象都属于对地址空间的引用,其值并不是具体的某种类型值,而是一个地址空间。
2.指针所指向的是单个类型值得地址空间,而对象所指向得是由多个类型所组成得一个集合类型的地址空间,也就是类类型得地址空间。
对象的构造与析构
1.构造函数:构造函数是用来创建和初始化对象得一个成员方法,构造函数的声明和普通函数的声明类似,不同的是将函数标识符 Procedure改为 Constructor。
构造函数分为有参构造函数和无参构造函数。
构造函数虽然没有在方法声明时明确的给出返回类型,但构造函数的确返回了一个指向自身类的一个类型,所以没有必要明确指定构造函数的返回类型。
一个类中可以定义多个构造函数,不同的构造函数就可以创建不同的对象,多个对象就会有多种表现形态,不同的形态就会产生不同的属性。
构造函数关键字为 Constructor.
type TPerson = class Fname: String; Fsex: Boolean; public constructor Create();overload;//重载使用overload constructor Create(MyName: String;sex: Boolean);overload; end; implementation var chinese: TPerson; { TPerson } constructor TPerson.Create; begin Fname:= '张三'; Fsex:= True; end; constructor TPerson.Create(MyName: String; sex: Boolean); begin Fname:= MyName; Fsex:= sex; end;
类也可以不声明构造函数,当类被创建时会自动调用父类的构造函数,如果在声明一个类时未显式指定所继承的父类,在类创建时会自动调用 TObject 类的构造函数,因为
当一个新类在创建时并未指明父类时,默认得父类都是 TObject 类。
构造函数的作用与工作步骤:要想实例化一个类的对象(创建对象),就必须使用该类的名称调用其构造函数。
var chinese: TPerson; begin chinese:= TPerson.Create('范思哲',true); end;
1.为对象在堆中分配一块存储区。
2.将类中声明的变量分配在这块区域上,并初始化各类型变量的值。
3.通过构造函数中的代码为类中的变量赋值。
4.构造函数最后返回这个类的一个引用赋值给要创建的对象。
匿名对象:一个局部对象每次使用完就要释放,像这样的对象没有必要去声明,通过匿名对象就可以完成这样的操作。比如可以当做参数进行传递,但是无法在传参之前做其他的事情。匿名对象无需释放(析构)。
with TPerson.Create()do begin SetName('范思哲'); end;
析构函数:析构函数的与构造函数的作用正好相反,构造函数的是用来创建对象的,而析构函数是释放对象的。析构函数的作用是释放对象在堆内存中所占用的地址空间,
destructor Destory();override;
析构函数关键字为 Destructor.一般来说析构函数都不指定参数,因为析构函数的作用是将类中所声明的变量释放,而这些变量又是当前类所已知的,所以不需要指定参数。
析构函数声明时通常会在函数后面加上 Override 指示符,表示用来覆盖从父类继承过来的同名析构函数,也就是重写。
析构函数工作步骤:析构函数执行自身方法中的代码,释放类中所定义的的其他类的对象或类变量。析构函数调用从父类继承来的析构函数,释放所继承的类成员。
类与对象的关系:类就是符合某一类事物的共同特性和行为的抽象,而对象就是为这一类事物创造出具有独特风格的具体事物。每次为类创建一个新对象时都会在堆内存中重新创建一个和类一样大小的
区域给对象,这样每一个对象就会有自己的独立属性和方法,互不影响,各不相同。
每个类中的方法都有一个隐含的名为Self 的指针,该指针在对象被创建时才有效,而且类会为每一个对象都分配一个Self 指针。这样对象调用类中的方法时就会通过Self 指针调性调用,
相互之间才不会受到影响。
free 并不能将对象置为 nil