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

📄 ch03.htm

📁 delphi自学的好教材!特别适合刚刚起步学习delphi的人员!同样对使用者具有参考价值!
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<PRE>Object Pascal uses properties to control the access to private fields. A property can be read/write, read-only, or write-only (although write-only properties are rare). A property can have a read method that is called when the property is read, and a write method when a property is written to. Neither is required, however, because a property can have direct access to the private field. These read and write methods are called any time the property is accessed. The write method is particularly important, as it can be used to validate input or to carry out other tasks when the property is assigned a value. In this way the private field is never accessed directly, but always through a property. I'm getting ahead of myself again so I'll leave it at that for now. Properties are discussed in detail on Day 5.</PRE><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Some OOP extremists say that fields should never be public. They	would advise you to use properties to access all fields. On the other end of the	spectrum is the group that recommends making all your fields public. The truth lies	somewhere in between. Some fields are noncritical and can be left public if doing	so is more convenient. Other fields are critical to the way the class operates and	should not be made public. If you are going to err, it is better to err on the side	of making fields private. <HR></BLOCKQUOTE><P>When you create an instance of a class, each class has its own data. You can assigna value to the variable Left in one instance of a class and assign a different valueto the Left variable in a different instance of the class--for example,</P><P><PRE>Rect1 := TMyRect.CreateVal(100, 100, 500, 500);Rect2 := TMyRect.CreateVal(0, 0, 100, 100);</PRE><P>This code creates two instances of the TMyRect class. Although these two instancesare identical in terms of their structure, they are completely separate in memory.Each instance has its own data. In the first case, the Left field would have a valueof 100. In the second case it would have a value of 0. It's like new cars on theshowroom floor: Every model of a particular car comes from the same mold, but theyare all separate objects. They all vary in their color, upholstery style, features,and so on.</P><P><H3><A NAME="Heading15"></A>Methods</H3><P><I>Methods</I> are functions and procedures that belong to your class. They arelocal to the class and don't exist outside the class. Methods can be called onlyfrom within the class itself or through an instance of the class. They have accessto all public, protected, and private fields of the class. Methods can be declaredin the private, protected, or public sections of your class. Good class design requiresthat you think about which of these sections your methods should go into.</P><P>* <I>Public methods</I>, along with properties, represent the user interface tothe class. It is through the public methods that users of the class access the classto gain whatever functionality it provides. For example, let's say you have a classthat plays and records waveform audio. Public methods might include methods namedOpen, Play, Record, Save, Rewind, and so on.</P><UL>	<LI><I>Private methods</I> are methods that the class uses internally to &quot;do	its thing.&quot; These methods are not intended to be called by users of the class;	they are private in order to hide them from the outside world. Frequently a class	has startup chores to perform when the class is created (for example, you have already	seen that the constructor is called when a class is created). In some classes the	startup processing might be significant, requiring many lines of code. To remove	clutter from the constructor, a class might have an Init method that is called from	the constructor to perform those startup tasks. This method would never be called	directly by a user of the class. In fact, more than likely bad things would happen	if this method were called by a user at the wrong time, so the method is private	in order to protect both the integrity of the class and the user.	<P>	<LI><I>Protected methods</I> are methods that cannot be accessed by the outside world	but can be accessed by classes derived from this class. I haven't talked yet about	classes being derived from other classes; I'll save that discussion for a little	later when it will make more sense. I discuss deriving classes in the section &quot;Inheritance.&quot;</UL><P>Methods can be declared as <I>class methods</I>. A class method operates morelike a regular function or procedure than a method of a class. Specifically, a classmethod cannot access fields or other methods of the class. (In just a bit I'll tellyou why this restriction exists.) Most of the time, you will not use class methods,so I won't go into any detail on them.</P><P><H3><A NAME="Heading16"></A>About Self</H3><P><strong>New Term:</strong> All classes have a hidden field called Self. Self is a pointerto the instance of the class in memory.</P><P>Obviously, this will require some explanation. First, let's take a look at howthe TMyRect class would look if Self were not a hidden field:</P><P><B>TMyRect = class</B></P><P><PRE>private  Self : TMyRect;  Left : Integer;  Top : Integer;  Right : Integer;  Bottom : Integer;  Text : PChar;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;</PRE><P>This is effectively what the TMyRect class looks like to the compiler. When aclass object is created, the Self pointer is automatically initialized to the addressof the class in memory:</P><P><PRE>Rect := TMyRect.CreateVal(0, 0, 100, 100);{ Now `Rect' and `Rect.Self' have the same value   } { because both contain the address of the object in memory. } </PRE><P>&quot;But,&quot; you ask, &quot;what does Self mean?&quot; Remember that eachclass instance gets its own copy of the class's fields. But all class instances sharethe same set of methods for the class (there's no point in duplicating that codefor each instance of the class). How does the compiler figure out which instancegoes with which method call? All class methods have a hidden Self parameter thatgoes with them. To illustrate, let's say you have a function for the TMyRect classcalled GetWidth. It would look like this:</P><P><B>function TMyRect.GetWidth : Integer;</B></P><P><PRE>begin  Result := Right - Left;end;</PRE><P>That's how the function looks to you and me. To the compiler, though, it lookssomething like this:</P><P><PRE>function TMyRect.GetWidth : Integer;begin  Result := Self.Right - Self.Left;end;</PRE><P>That's not exactly accurate from a technical perspective, but it's close enoughfor this discussion. In this code you can see that Self is working behind the scenesto keep everything straight for you. You don't have to worry about how that happens,but you need to know that it does happen.</P><BLOCKQUOTE>	<P><HR><strong>CAUTION:</strong> Never modify the Self pointer. You can use it to pass a pointer	to your class to other methods or as a parameter in constructing other classes, but	don't change its value. Learn to treat Self as a read-only variable. <HR></BLOCKQUOTE><PRE>Although Self works behind the scenes, it is still a variable that you can access from within the class. As an illustration, let's take a quick peek into VCL. Most of the time, you will create components in VCL by dropping them on the form at design time. When you do that, Delphi creates a pointer to the component and does all sorts of housekeeping chores on your behalf, saving you from concerning yourself with the technical end of things. Sometimes, however, you will create a component at runtime. VCL insists (as all good frameworks do) on keeping track of which child objects belong to which parent. For example, let's say you want to create a button on a form when another button is clicked. You need to tell VCL what the parent of the new button is. The code would look like this:</PRE><PRE>procedure TForm1.Button1Click(Sender: TObject);var  Button : TButton;begin  Button := TButton.Create(Self);  Button.Parent  := Self;  Button.Left    := 20;  Button.Top     := 20;  Button.Caption := `Click Me';end;</PRE><P>In this code, you can see that Self is used in the constructor (this sets theOwner property of the button, but I'll get into that later when I cover VCL componentson Day 7, &quot;VCL Components&quot;) and also that it is assigned to the Parentproperty of the newly created button. This is how you will use the Self pointer thevast majority of the time in your Delphi applications.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Earlier I said that class methods can't access class fields. The	reason this is true is because class methods don't have a hidden Self parameter;	regular methods do. Without Self, a method cannot access class fields. <HR></BLOCKQUOTE><P>Don't worry too much about Self right now. When you begin to use VCL, it willquickly become clear when you are required to use Self in your Delphi applications.</P><P><H3><A NAME="Heading17"></A>A Class Example</H3><PRE>Right now it would be nice if you could see an example of a class. Listing 3.1 shows a unit that contains a class called TAirplane. This class could be used by an aircraft controller program. The class enables you to command an airplane by sending it messages. You can tell the airplane to take off, to land, or to change its course, altitude, or speed. First take a look at the unit and then I'll discuss what is going on within this class.</PRE><H4>LISTING 3.1. AIRPLANU.PAS.</H4><PRE>unit AirplanU;interfaceuses  SysUtils;const  { Airplane types. }   Airliner     = 0;  Commuter     = 1;  PrivateCraft = 2;  { Status constants. }   TakingOff    = 0;  Cruising     = 1;  Landing      = 2;  OnRamp       = 3;  { Message constants. }   MsgChange    = 0;  MsgTakeOff   = 1;  MsgLand      = 2;  MsgReport    = 3;type  TAirplane = class  private    Name     : string;    Speed    : Integer;    Altitude : Integer;    Heading  : Integer;    Status   : Integer;    Kind     : Integer;    Ceiling  : Integer;  protected    procedure TakeOff(Dir : Integer); virtual;    procedure Land; virtual;  public    constructor Create(AName : string; AKind : Integer = Airliner);    function SendMessage(Msg : Integer; var Response : string;       Spd : Integer; Dir : Integer; Alt : Integer) : Boolean;    function GetStatus(var StatusString : string) : Integer; overload; &#194;virtual;    function GetStatus : Integer; overload;    function GetSpeed : Integer;</PRE><P><B>function GetHeading : Integer;</B></P><P><PRE>    function GetAltitude : Integer;    function GetName : string;  end;implementationconstructor TAirplane.Create(AName : string; AKind : Integer);begin  inherited Create;  Name     := AName;  Kind     := AKind;  Status   := OnRamp;  case Kind of    Airliner : Ceiling := 35000;    Commuter : Ceiling := 20000;    PrivateCraft : Ceiling := 8000;  end;end;procedure TAirplane.TakeOff(Dir : Integer);begin  Heading := Dir;  Status  := TakingOff;end;procedure TAirplane.Land;begin  Speed    := 0;  Heading  := 0;  Altitude := 0;  Status   := OnRamp;end;function TAirplane.SendMessage(Msg : Integer; var Response : string;   Spd : Integer; Dir : Integer; Alt : Integer) : Boolean;begin  Result := True;  { Do something based on which command was sent. }   case Msg of    MsgTakeOff :      { Can't take off if already in the air! }       if status &lt;&gt; OnRamp then begin        Response := Name + `: I''m already in the air!';        Result := False;      end else        TakeOff(dir);    MsgChange :      begin        { Check for bad commands and exit if any found. }         if Spd &gt; 500 then          Response := `Command Error: Speed cannot be more than 500.';        if Dir &gt; 360 then          Response := `Command Error: Heading cannot be over 360 &#194;degrees.';        if Alt &lt; 100 then          Response := Name + `: I''d crash!';        if Alt &gt; Ceiling then          Response := Name + `: I can''t go that high.';        if (Spd = 0) and (Dir = 0) and (Alt = 0) then          Response := Name + `: Huh?';        if Response &lt;&gt; `' then begin          Result := False;          Exit;        end;        { Can't change status if on the ground. }         if status = OnRamp then begin          Response := Name + `: I''m on the ground.';          Result := False;        end else begin          Speed := Spd;          Heading := Dir;          Altitude := Alt;          Status := Cruising;        end;      end;

⌨️ 快捷键说明

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