Pascal-classes
パスカル-クラス
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 |
これらのメンバーは常にアクセス可能です。 |
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}を使用する必要があります。