⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch03.htm

📁 delphi自学的好教材!特别适合刚刚起步学习delphi的人员!同样对使用者具有参考价值!
💻 HTM
📖 第 1 页 / 共 5 页
字号:
  procedure StartupProcedure;public  HaveKey : Boolean;  Start : Boolean;  procedure SetGear(Gear : Integer);  procedure Accelerate(Acceleration : Integer);  procedure Brake(Factor : Integer);  procedure Turn(Direction : Integer);  procedure ShutDown;end;</PRE><P>Notice how you break the class organization down into the three access levels.You might not use all of the access levels in a given class. For example, I am notusing the published access level in this example. You are not required to use anyof the access levels if you don't want, but typically you will have a public anda private section at the least.</P><P><H3><A NAME="Heading12"></A>Constructors</H3><P>Classes in Object Pascal have a special method called the constructor.</P><P><strong>New Term:</strong> The <I>constructor</I> is a method that is used to createan instance of a class.</P><P>The constructor is used to initialize any class member variables, allocate memorythe class will need, or do any other startup tasks. The TVehicle example you justsaw does not have a constructor. If you don't provide a constructor, you can usethe base class's constructor when you create the class. (If not otherwise specified,all Object Pascal classes are derived from TObject. The TObject class has a constructorcalled Create, so it is this constructor that will be called if you don't providea constructor. I'll discuss base classes and inheritance later in the section &quot;Inheritance.&quot;)Although using the base class's constructor is fine for simple classes, you willalmost always provide a constructor for classes of any significance. The constructorcan be named anything, but it must be declared using the constructor keyword. Thisis what distinguishes it as a constructor. Given that, let's add a constructor declarationto the TVehicle class:</P><P><B>TVehicle = class</B></P><P><PRE>private  CurrentGear : Integer;  Started : Boolean;  Speed : Integer;  procedure StartElectricalSystem;  procedure StartEngine;protected  procedure StartupProcedure;public  HaveKey : Boolean;  Start : Boolean;  procedure SetGear(Gear : Integer);  procedure Accelerate(Acceleration : Integer);  procedure Break(Factor : Integer);  procedure Turn(Direction : Integer);  procedure ShutDown;  constructor Create;  { the constructor } end;</PRE><P>Notice that the constructor is a special type of method. It does not have a returntype because a constructor cannot return a value. If you try to add a return typeto the constructor declaration, you will get a compiler error.</P><P>A class can have more than one constructor. This can be accomplished in two differentways. The first way is to simply give the constructor a different name--for example,</P><P><PRE>TVehicle = class  { rest of class deleted }   constructor Create;   constructor CreateModel(Model : string); end;</PRE><P>This example shows two constructors, one called Create and the other called CreateModel.</P><P>Another way to declare multiple constructors is through method overloading, whichI discussed yesterday. Here is an example that uses constructors with the same name,but with different parameters:</P><P><B>TVehicle = class</B></P><P><PRE>  { rest of class deleted }   constructor Create; overload;   constructor Create(AOwner : TObject);  overload;end;</PRE><P>Because method overloading is new in Delphi 4, I don't expect to see this wayof declaring multiple constructors used very much in Delphi programs. The traditionalmethod is to declare constructors with different names, and I suspect that trendwill continue for quite some time. Still, both methods are legal and either one canbe used.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> If you create components for the retail market, you should be sure	that your components' constructors have different parameter lists. This will ensure	that your components will work with C++Builder as well as with Delphi (C++Builder	does not have named constructors, so method overloading is used to differentiate	constructors). Even if you don't plan on selling your components to the C++Builder	market, you'd be wise to plan ahead for the possibility. <HR></BLOCKQUOTE><P>What's the point of multiple constructors? Multiple constructors provide differentways of creating a class. For instance, a class can have a constructor that takesno parameters and a constructor that takes one or more parameters to initialize fieldsto certain values. For example, let's say you have a class called TMyRect that encapsulatesa rectangle (rectangles are frequently used in Windows programming). This class couldhave several constructors. It could have a default constructor that sets all thefields to 0, and another constructor that enables you to set the class's fields throughthe constructor. First, let's take a look at how the class declaration might look:</P><P><PRE>TMyRect = classprivate  Left : Integer;  Top : Integer;  Right : Integer;  Bottom : Integer;public  function GetWidth : Integer;  function GetHeight : Integer;  procedure SetRect(ALeft, ATop, ARight, ABottom : Integer);  constructor Create;  constructor CreateVal(ALeft, ATop, ARight, ABottom : Integer);</PRE><P><B>end;</B></P><P>The definitions for the constructors would look something like this:</P><P><PRE>constructor TMyRect.Create;begin  inherited Create;  Left   := 0;  Top    := 0;  Right  := 0;  Bottom := 0;end;constructor TMyRect.CreateVal(ALeft, ATop, ARight, ABottom : Integer);begin  inherited Create;  Left   := ALeft;  Top    := ATop;  Right  := ARight;  Bottom := ABottom;end;</PRE><P>The first constructor simply initializes each field to 0. The second constructortakes the parameters passed and assigns them to the corresponding class fields. Thevariable names in the parameter list are local to the constructor, so each of thevariable names begins with an <I>A</I> to differentiate between the local variablesand the class fields (the use of the leading <I>A</I> is customary for Delphi programs).Notice the use of the inherited keyword in the constructors. I'll talk about theinherited keyword later in the section &quot;Inheritance.&quot; I wanted to pointit out here just so you would know I'm not leaving you in the dark.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> It's not strictly necessary to initialize the fields to 0 as the	Create constructor does here. All fields are automatically initialized to 0 when	an object of the class is created. <HR></BLOCKQUOTE><P><strong>New Term:</strong> <I>Instantiation</I> is the creation of an object, calledan <I>instance</I>, of a class.</P><P><PRE>So how do you use one of these constructors instead of the other? You do that when you instantiate an instance of a class. The following code snippet creates two instances of the TMyRect class. The first uses the Create constructor and the second uses the CreateVal constructor:</PRE><PRE>var  Rect1 : TMyRect;  Rect2 : TMyRect;begin  Rect1 := TMyRect.Create;  Rect2 := TMyRect.CreateVal(0, 0, 100, 100);end;</PRE><P>You can have as many constructors as you like as long as they all have differentnames or, if overloaded, as long as they follow the rules of method overloading.</P><P>There is one thing that I need to point out about the previous example: Both instancesof the TMyRect class are allocated dynamically. Earlier I said that you allocatememory for an object dynamically by calling the GetMem procedure. Now I seem to becontradicting myself, but in truth I am not. The reason is that memory for ObjectPascal classes is <I>always</I> allocated dynamically. Although that is not trueof records, it is true of classes. That also means that the previous code snippetleaks memory because I didn't free the memory associated with the two classes. I'lltalk about that next. Because all Object Pascal classes are created on the heap,all class variables are, therefore, pointers. The Rect1 and Rect2 variables in thepreceding example are both pointers to the TMyRect class.</P><P><H3><A NAME="Heading13"></A>Destructors</H3><P><strong>New Term:</strong> The <I>destructor</I> is a special method that is automaticallycalled just before the object is destroyed.</P><P>The destructor can be considered the opposite of the constructor. It is usuallyused to free any memory allocated by the class or do any other cleanup chores. Aclass is not required to have a destructor because the base class's destructor canbe used instead. Like a constructor, a destructor has no return value.</P><P>Although a class can have multiple destructors, it is not something that is typicallydone. If you have just one destructor, you should name it Destroy. This is more thanjust tradition. When you free an instance of a class (remove it from memory), youcall the Free method. Free is a method of the TObject class that calls the class'sDestroy method just before the class is removed from memory. This is the typicalway to free the memory associated with a class. Here's an example:</P><P><PRE>Rect1 := TMyRect.Create;{ Do some things with Rect1. } { ... } { Now delete Rect1. } Rect1.Free;</PRE><PRE>The example in the &quot;Constructors&quot; section would actually leak memory because the two TMyRect objects were never freed.</PRE><P>The following shows the updated code for the TMyRect class, complete with destructor(some code removed for brevity):</P><P><PRE>TMyRect = classprivate  Left : Integer;  Top : Integer;  Right : Integer;  Bottom : Integer;  Text : PChar;     { new field } public  function GetWidth : Integer;  function GetHeight : Integer;  procedure SetRect(ALeft, ATop, ARight, ABottom : Integer);  constructor Create;  constructor CreateVal(ALeft, ATop, ARight, ABottom : Integer);  destructor Destroy; override;end;constructor TMyRect.Create;begin  inherited Create;  { Allocate memory for a null-terminated string. }   Text := AllocMem(1024);end;destructor TMyRect.Destroy;begin  { Free the allocated memory. }   FreeMem(Text);  inherited Destroy;end;</PRE><P>The modified version of the TMyRect class allocates storage for a null-terminatedstring (a PChar) named Text in its constructor and frees that storage in the destructor.(I can't think of a good reason for a class that handles rectangles to have a textfield, but you never know! It's just an example, after all.)</P><P>Take a closer look at the declaration of the destructor in the TMyRect class declaration.It looks like this:</P><P><PRE>destructor Destroy; override;</PRE><PRE>Notice the override keyword at the end of the declaration. This keyword tells the compiler that you are overriding a method that is also found in the base class. I'm getting ahead of myself again, so I'll continue this discussion later in the section entitled &quot;Inheritance.&quot; (I keep saying that, so I'll bet you expect that section to be really good!)</PRE><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Typically, you will call inherited as the first statement in your	constructor and the last statement in your destructor. <HR></BLOCKQUOTE><H3><A NAME="Heading14"></A>Data Fields</H3><P><I>Data fields</I> of a class are simply variables that are declared in the classdeclaration; they can be considered as variables that have class scope. Fields inclasses are essentially the same as fields in records except that their access canbe controlled by declaring them as private, public, or protected. Regardless of afield's access, it is available for use in all methods of the class. Depending onthe field's access level, it can be visible outside the class as well. Private andprotected fields, for example, are private to the class and cannot be seen outsidethe class. Public fields, however, can be accessed from outside the class but onlythrough an object. Take the TMyRect class declared previously, for example. It hasno public fields. You could try the following, but you'll get a compiler error:</P><P><PRE>Rect := TMyRect.CreateVal(0, 0, 100, 100);Rect.Left := 20; { compiler error! } </PRE><P>The compiler error will say Undeclared identifier: `Left'. The compiler is tellingyou that Left is a private field, and you can't get to it. If Left were in the publicsection of the class declaration, this code would compile.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> The preceding discussion of private data fields holds true if the	TMyRect class were declared in a separate unit, but not true if the TMyRect class	is declared in the unit where it is used. Classes contained in the same unit have	what are sometimes called <I>friend privileges</I>, which means that the classes	can access each other's private data fields. This applies only to classes declared	in the same unit. <HR></BLOCKQUOTE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -