Pascal-classes

提供:Dev Guides
移動先:案内検索

パスカル-クラス

Pascalオブジェクトがオブジェクト指向のパラダイムのいくつかの特徴を示すことを見てきました。 カプセル化、データ隠蔽、継承を実装しますが、制限もあります。 たとえば、Pascalオブジェクトはポリモーフィズムに参加しません。 したがって、クラスは、プログラム、特にGUIベースのソフトウェアに適切なオブジェクト指向の動作を実装するために広く使用されています。

クラスはオブジェクトとほぼ同じ方法で定義されますが、オブジェクト自体ではなく、オブジェクトへのポインタです。 技術的には、これはクラスがプログラムのヒープに割り当てられ、オブジェクトがスタックに割り当てられることを意味します。 つまり、変数をオブジェクト型として宣言すると、スタック上でオブジェクトのサイズと同じくらいのスペースを占有しますが、クラス型の変数を宣言すると、常にポインターのサイズを使用しますスタック上。 実際のクラスデータはヒープ上にあります。

Pascalクラスの定義

クラスは、型宣言を使用して、オブジェクトと同じ方法で宣言されます。 クラス宣言の一般的な形式は次のとおりです-

type class-identifier = class
   private
      field1 : field-type;
      field2 : field-type;
        ...

   public
      constructor create();
      procedure proc1;
      function f1(): function-type;
end;
var classvar : class-identifier;

以下の重要な点に注意する価値-

  • クラス定義は、プログラムの型宣言部分のみに含まれている必要があります。
  • クラスは、 class キーワードを使用して定義されます。
  • フィールドは、クラスの各インスタンスに存在するデータ項目です。
  • メソッドはクラスの定義内で宣言されます。
  • Rootクラスには Create と呼ばれる定義済みのコンストラクターがあります。 すべての抽象クラスとすべての具象クラスはルートの子孫なので、すべてのクラスには少なくとも1つのコンストラクターがあります。
  • Rootクラスには Destroy と呼ばれる定義済みのデストラクタがあります。 すべての抽象クラスとすべての具象クラスはルートの子孫なので、すべてのクラスには少なくとも1つのデストラクタがあります。

長さと幅、これらのデータメンバーを操作するメンバー関数、および四角形を描画するプロシージャの2つの整数型データメンバーを持つRectangleクラスを定義しましょう。

type
   Rectangle = class
   private
      length, width: integer;

   public
      constructor create(l, w: integer);
      procedure setlength(l: integer);
      function getlength(): integer;
      procedure setwidth(w: integer);
      function getwidth(): integer;
      procedure draw;
end;

長方形クラスのインスタンスを作成して長方形を描画する完全なプログラムを作成しましょう。 これは、Pascalオブジェクトの説明で使用したものと同じ例です。 次の例外を除き、両方のプログラムがほぼ同じであることがわかります-

  • クラスを使用するには、\ {$ mode objfpc}ディレクティブを含める必要があります。
  • コンストラクターを使用するには、\ {$ m +}ディレクティブを含める必要があります。 *クラスのインスタンス化は、オブジェクトのインスタンス化とは異なります。 変数を宣言するだけではインスタンス用のスペースは作成されません。コンストラクタcreateを使用してメモリを割り当てます。

ここに完全な例があります-

{$mode objfpc}//directive to be used for defining classes
{$m+}         //directive to be used for using constructor

program exClass;
type
   Rectangle = class
   private
      length, width: integer;

   public
      constructor create(l, w: integer);
      procedure setlength(l: integer);

      function getlength(): integer;
      procedure setwidth(w: integer);

      function getwidth(): integer;
      procedure draw;
end;
var
   r1: Rectangle;

constructor Rectangle.create(l, w: integer);
begin
   length := l;
   width := w;
end;

procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;

procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;

function Rectangle.getlength(): integer;
begin
   getlength := length;
end;

function Rectangle.getwidth(): integer;
begin
   getwidth := width;
end;

procedure Rectangle.draw;
var
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write('* ');
      writeln;
   end;
end;

begin
   r1:= Rectangle.create(3, 7);

   writeln(' Draw Rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   r1.setlength(4);
   r1.setwidth(6);

   writeln(' Draw Rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
end.

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Draw Rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw Rectangle: 4 by 6
* * * * * *
* * * * * *
* * * * * *
* * * * * *

クラスメンバーの可視性

可視性は、クラスメンバーのアクセシビリティを示します。 パスカルクラスのメンバーは5種類の可視性を持っています-

Sr.No Visibility & Accessibility
1
  • Public*

これらのメンバーは常にアクセス可能です。

2

Private

これらのメンバーは、クラス定義を含むモジュールまたはユニットでのみアクセスできます。 クラスメソッドの内部または外部からアクセスできます。

3

Strict Private

これらのメンバーには、クラス自体のメソッドからのみアクセスできます。 同じユニット内の他のクラスまたは子孫クラスはそれらにアクセスできません。

4

Protected

これはprivateと同じですが、これらのメンバーは、他のモジュールで実装されている場合でも、子孫型にアクセスできます。

5

Published

これはPublicと同じですが、コンパイラが\ {$ M +}状態にある場合、コンパイラはこれらのクラスの自動ストリーミングに必要な型情報を生成します。 パブリッシュされたセクションで定義されたフィールドは、クラスタイプである必要があります。

Pascalクラスのコンストラクタとデストラクタ

コンストラクターは特別なメソッドであり、オブジェクトが作成されるたびに自動的に呼び出されます。 したがって、コンストラクター関数を介して多くのことを初期化することにより、この動作を最大限に活用します。

Pascalは、コンストラクターを定義するcreate()と呼ばれる特別な関数を提供します。 コンストラクター関数には、好きなだけ引数を渡すことができます。

次の例では、Booksという名前のクラスに1つのコンストラクターを作成し、オブジェクトの作成時に書籍の価格とタイトルを初期化します。

program classExample;

{$MODE OBJFPC}//directive to be used for creating classes
{$M+}//directive that allows class constructors and destructors
type
   Books = Class
   private
      title : String;
      price: real;

   public
      constructor Create(t : String; p: real);//default constructor

      procedure setTitle(t : String);//sets title for a book
      function getTitle() : String;//retrieves title

      procedure setPrice(p : real);//sets price for a book
      function getPrice() : real;//retrieves price

      procedure Display();//display details of a book
end;
var
   physics, chemistry, maths: Books;

//default constructor
constructor Books.Create(t : String; p: real);
begin
   title := t;
   price := p;
end;

procedure Books.setTitle(t : String);//sets title for a book
begin
   title := t;
end;

function Books.getTitle() : String;//retrieves title
begin
   getTitle := title;
end;

procedure Books.setPrice(p : real);//sets price for a book
begin
   price := p;
end;

function Books.getPrice() : real;//retrieves price
begin
   getPrice:= price;
end;

procedure Books.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price:5:2);
end;

begin
   physics := Books.Create('Physics for High School', 10);
   chemistry := Books.Create('Advanced Chemistry', 15);
   maths := Books.Create('Algebra', 7);

   physics.Display;
   chemistry.Display;
   maths.Display;
end.

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Title: Physics for High School
Price: 10
Title: Advanced Chemistry
Price: 15
Title: Algebra
Price: 7

createという暗黙のコンストラクターと同様に、クラスで使用されているすべてのリソースを解放できる暗黙的なデストラクターメソッドdestroyもあります。

継承

Pascalクラス定義は、オプションで親クラス定義から継承できます。 構文は次のとおりです-

type
childClas-identifier = class(baseClass-identifier)
< members >
end;

次の例では、Booksクラスを継承し、要件に基づいて機能を追加する小説クラスを提供します。

program inheritanceExample;

{$MODE OBJFPC}//directive to be used for creating classes
{$M+}//directive that allows class constructors and destructors

type
   Books = Class
   protected
      title : String;
      price: real;

   public
      constructor Create(t : String; p: real);//default constructor

      procedure setTitle(t : String);//sets title for a book
      function getTitle() : String;//retrieves title

      procedure setPrice(p : real);//sets price for a book
      function getPrice() : real;//retrieves price

      procedure Display(); virtual;//display details of a book
end;
( *Creating a derived class* )

type
   Novels = Class(Books)
   private
      author: String;

   public
      constructor Create(t: String); overload;
      constructor Create(a: String; t: String; p: real); overload;

      procedure setAuthor(a: String);//sets author for a book
      function getAuthor(): String;//retrieves author name

      procedure Display(); override;
end;
var
   n1, n2: Novels;

//default constructor
constructor Books.Create(t : String; p: real);
begin
   title := t;
   price := p;
end;

procedure Books.setTitle(t : String);//sets title for a book
begin
   title := t;
end;

function Books.getTitle() : String;//retrieves title
begin
   getTitle := title;
end;

procedure Books.setPrice(p : real);//sets price for a book
begin
   price := p;
end;

function Books.getPrice() : real;//retrieves price
begin
   getPrice:= price;
end;

procedure Books.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price);
end;

( *Now the derived class methods * )
constructor Novels.Create(t: String);
begin
   inherited Create(t, 0.0);
   author:= ' ';
end;

constructor Novels.Create(a: String; t: String; p: real);
begin
   inherited Create(t, p);
   author:= a;
end;

procedure Novels.setAuthor(a : String);//sets author for a book
begin
   author := a;
end;

function Novels.getAuthor() : String;//retrieves author
begin
   getAuthor := author;
end;

procedure Novels.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price:5:2);
   writeln('Author: ', author);
end;

begin
   n1 := Novels.Create('Gone with the Wind');
   n2 := Novels.Create('Ayn Rand','Atlas Shrugged', 467.75);
   n1.setAuthor('Margaret Mitchell');
   n1.setPrice(375.99);
   n1.Display;
   n2.Display;
end.

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Title: Gone with the Wind
Price: 375.99
Author: Margaret Mitchell
Title: Atlas Shrugged
Price: 467.75
Author: Ayn Rand

以下の重要な点に注意する価値-

  • Booksクラスのメンバーは、可視性が「保護」されています。
  • Novelsクラスには2つのコンストラクターがあるため、関数のオーバーロードには overload 演算子が使用されます。
  • Books.Displayプロシージャは virtual と宣言されているため、Novelsクラスの同じメソッドで*オーバーライド*できます。
  • Novels.Createコンストラクターは、 inherited キーワードを使用して基本クラスコンストラクターを呼び出します。

インターフェース

インターフェイスは、実装者に共通の関数名を提供するために定義されています。 異なる実装者は、要件に応じてこれらのインターフェイスを実装できます。 インターフェースは、開発者によって実装されるスケルトンと言えます。 以下は、インターフェイスの例です-

type
   Mail = Interface
      Procedure SendMail;
      Procedure GetMail;
   end;

   Report = Class(TInterfacedObject,  Mail)
      Procedure SendMail;
      Procedure GetMail;
   end;

クラスがインターフェイスを実装する場合、インターフェイスのすべてのメソッドを実装する必要があることに注意してください。 インターフェイスのメソッドが実装されていない場合、コンパイラはエラーを返します。

抽象クラス

抽象クラスは、インスタンス化することはできず、継承されるだけです。 抽象クラスは、このように、クラス定義に単語シンボル抽象を含めることによって指定されます-

type
   Shape = ABSTRACT CLASS (Root)
      Procedure draw; ABSTRACT;
      ...
   end;

抽象クラスから継承する場合、親のクラス宣言で抽象とマークされたすべてのメソッドは、子によって定義される必要があります。さらに、これらのメソッドは同じ可視性で定義する必要があります。

静的キーワード

クラスメンバまたはメソッドを静的として宣言すると、クラスのインスタンス化を必要とせずにアクセスできます。 静的として宣言されたメンバーは、インスタンス化されたクラスオブジェクトではアクセスできません(ただし、静的メソッドはアクセスできます)。 次の例は、概念を示しています-

program StaticExample;
{$mode objfpc}
{$static on}
type
   myclass=class
      num : integer;static;
   end;
var
   n1, n2 : myclass;
begin
   n1:= myclass.create;
   n2:= myclass.create;
   n1.num := 12;
   writeln(n2.num);
   n2.num := 31;
   writeln(n1.num);
   writeln(myclass.num);
   myclass.num := myclass.num + 20;
   writeln(n1.num);
   writeln(n2.num);
end.

上記のコードをコンパイルして実行すると、次の結果が生成されます-

12
31
31
51
51

静的メンバーを使用するには、ディレクティブ\ {$ static on}を使用する必要があります。