無料の開発環境 Delphi Starter Edition で Object Pascal 言語を優しく学ぶ 第7回 「オブジェクト指向」その2

#Delphi Starter Edition チュートリアルシリーズ シーズン2 第7回 「オブジェクト指向」その2

[Delphi Starter Edition チュートリアルシリーズ シーズン2 第7回 「オブジェクト指向」その1](http://qiita.com/kazaiso/items/c76eac60bdd4dd075fa3) の続きです。
[その1](http://qiita.com/kazaiso/items/c76eac60bdd4dd075fa3)ではオブジェクト指向の全体の説明と隠蔽＆公開の話を説明してきました。 その2ではいよいよオブジェクト指向の「継承」の話に入ります。

その１でも記述しましたが、記述しているコード例のいくつかはGithubに上げているサンプルコードで確認することができます。
https://github.com/kazaiso/Starter_Tutorial_season2_20170306


では続きです…

###**クラスの継承**
* 既にあるクラスのフィールドやメソッドを受け継いで新たなクラス定義が可能
  * 既存のクラスのフィールドやメソッドを受け継ぎつつ新たなフィールドやメソッドを追加したり、上書きすることが可能
  * いずれ実装される子クラスに、メソッドの実装をゆだねておく、といった定義も可能

クラスを継承してあらたなクラスを定義する場合の構文は以下のようになります

```delphi
type
   子となるクラス定義識別子 = class(継承元となるクラス定義識別子) 
  public
  //フィールド、メソッド… 
```
継承してあらたなクラスを定義するコード例は下記のようになります。

```delphi
type            //継承クラスの定義例  
  TDate = class //親となるTDateクラス（ベースクラス）
  private
    FDate: TDateTime; //日付を保持する TDateTime型 FDateフィールド
  public
//省略
    function GetText: string; //日付情報を文字化して渡すメソッド
//省略
  end;

type 
  TNewDate = class(TDate) //TDateから派生（TDateを継承）する 子クラス（サブクラス）
  public
    function GetText: string; //親の持つ GetTextメソッドをTNewDateクラス版に書き換えるための宣言
  end;
```

**このコードのポイント**

* 最初の`TDate` クラスは親となるクラスの定義です。次の`TNewDate`クラスが `TDate`クラスを継承して作っている新たな子のクラスです。（前週のチュートリアルや、その１で使っている`TDate`クラスです）
* 親のクラスで `GetText`メソッドを持っています。子のクラスで同名の`GetText`メソッドを定義して、その処理を変更する定義を行っています。

###**継承先での新しいメソッドへの書き換え実装例**
上のセクションで `TDate` クラスを継承して`TNewDate`クラスを定義しました。そして`TDate`クラスが持つ、`GetText`メソッドを上書きする同名の`GetText`メソッドを`TNewDate`クラスにも定義してありました。
ここでは継承先で同名のメソッド新しいメソッドへと書き換えるコード例を見てみます。

```delphi
implementation

{ TDate }
function TDate.GetText: string; //参考に掲載。親のGetTextメソッド実装部
begin
  Result := DateToStr(FDate); //親の元実装 ： ’2017/03/06’の文字列が返る
end;

{ TNewDate }
function TNewDate.GetText: string; //TNewDateクラスで親と同名のGetTextメソッドを新たに記述
begin
  Result := FormatDateTime('ggE年m月d日 (dddd)', FDate); //子の実装 ’平成29年3月6日 (月曜日)’の文字列が返る
end;
```
**このコードのポイント**

* 最初に実装してある`TDate.GetText`は親クラスが持っているもともとの`GetText`メソッドです。
*  `TNewDate.GetText`が今回新たに実装した継承クラス（子クラス）の `GetText`です。
*  `TNewDate.GetText`で特に小難しいテクニックを使わず、普通に`子クラス定義識別子.メソッド識別子`として実装します。
*  `TNewDate`クラスのフィールドとして`FDate`は定義していませんでしたが、問題なく使えます。これは親の`TDate`が`FDate: TDatetime;` のフィールドを持っているからで、「継承」を使った場合の特徴の一つとして、親クラスがもっているフィールドは子クラスにおいても同様に持っているものとして、新たに定義せずとも引き継いで使うことができるのです。※ちなみに子クラスの`TNewDate`で`GetText`を新たに定義しなければ、親の`TDade`クラスて定義・実装してある`GetText`をそのまま使うことができます。

###**親クラスと子クラスのメソッド動作の違い**
上のセクションで`TDate`クラスを継承して定義した`TNewDate`クラスの新メソッド`GetText`の実装を行いました。ここではその実装した`GetText`について、親のクラスと子のクラスでそれぞれ使ってみてどのように動作するか確認してみましょう。

```delphi
procedure TForm1.Button1Click(Sender: TObject);
var
  myDay: TDate;		//親クラスのオブジェクト識別子
  myNewDay: TNewDate;	//子クラスのオブジェクト識別子
begin
  myDay := TDate.Create;  	//親オブジェクトのCreate
  myNewDay := TNewDate.Create;	//子オブジェクトのCreate
  try
    show('親クラス: '+ myday.GetText);	//親オブジェクトのGetTextメソッドで文字列を取得して表示
    show('子クラス: '+ myNewDay.GetText);	//子オブジェクトのGetTextメソッドで文字列を取得して表示
  finally
    myDay.Free;		//親オブジェクトの解放
    myNewDay.Free;	//子オブジェクトの解放
  end;
```
**このコードでのポイント**

* 継承先で新たな同名メソッドを記述して動作を変更することが可能
  * **新**クラス(`TNewDate`)のオブジェクト識別子を使用した場合には、**新**クラス(`TNewDate`)が持つメソッドの処理が行われる
  * **親**クラス(`TDate`)のオブジェクト識別子を使用した場合には、**親**クラス(`TDate`)が持つメソッドの処理が行われる

* このコードを走らせた結果表示されるのが下記となります
  * `TDate`型ののオブジェクト識別子に`TDate`のオブジェクト参照が入っていて、その`GetText`を実行すると、`TDate`クラスの`GetText`メソッドが返す文字列であるyyyy/mm/dd の文字列が返ります。
  * `TNewDate`型のオブジェクト識別子に`TNewDate`のオブジェクト参照が入っていて、そのGetTextを実行すると、`TNewDate`クラスの`GetText`メソッドが返すフォーマットされた文字列が返ります。

![image](https://qiita-image-store.s3.amazonaws.com/0/145847/b4c3c6f1-9fee-495d-1ee0-26b8ca7e3dde.png)

このように親のクラスを継承した子のクラスで、親クラスの持つフィールド（やクラス）を引き継いで使いながら、また、親クラスの持っていたメソッドを上書き・更新して使うことができます。

###**classを作ると、ある一つのクラスを継承している**
* Delphi (Object Pascal) の`class`はデフォルトで `TObject` クラスを自動的に継承
  * `type TDate = class` の定義は  `type TDate = class(TObject)` 定義と同じ意味となる
  * すべてのクラスは基本的に `TObject` のサブクラス（子孫クラス）
<p></p><br>
* `Create`, `Destroy`, `Free` などは `TObject` で定義・実装されているメソッド
  * コンストラクタの実装例で使用した `inherited Create;` は、`TObject` の `Create` を実行
  * デストラクタの実装例で使用した `inherited;` は `TObject` の 同名の `Destroy` を実行 

>`type Tクラス定義識別子 = class` と書くと必ず TObjectを親として継承します。なのでコード上、わかりやすく `type Tクラス定義識別子 = class(TObject)`と書いても問題ありません。`TObject`を継承しない方法もありますが、チュートリアルシリーズでは割愛します

TObjectが持っているメソッドにいては下記のDocWikiを参照してください。
参考DocWiki: http://docwiki.embarcadero.com/Libraries/Berlin/ja/System.TObject

###**実は既に継承を使っています**
ここで、ちょっと寄り道。オブジェクト指向と、そのクラス継承がどんなに便利なものかを再確認していただくために…

クラスの継承の定義、実装、使い方の例を見てきましたが、Delphiを使っているフレンズはすでに継承を使っています。

* 自動的に作成されたフォーム（TForm1）もクラスTFormを継承
  * 「マルチデバイスアプリケーションの新規作成」を行ったときに、自動で作られているフォーム（ウインドウ）はすでに用意されているTFormを継承してTForm1として子クラスを自動で作っているものです。
  * 以下、自動で作られている定義を引用します（下記コード例ではボタンコンポーネントを一つ追加して、オンクリックイベントハンドラを追加してある状態）

```delphi
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private 宣言 }
  public
    { public 宣言 }
  end;
```
はい。継承を学んだ今、見てみると、継承してクラス定義をする記述がなされているのがわかりますよね。そして追加しているボタンなどはTButton(これもクラス）をフィールドとして追加していることが読めます。こうして親クラスを継承して子クラスを作り、カスタマイズして使っているわけです。Delphiのビジュアル開発もオブジェクト指向によるものであります。

###**親・祖先のクラス型のオブジェクト識別子の下位互換性**
継承を学んだところでさらに深みに入ってまいります。便利な使い方を説明する前に、先に知っておいていただきたいオブジェクト識別子の使い方があります。

* 親・祖先のオブジェクト識別子に、子のクラス型のオブジェクト参照を代入可能

上記ができると…

* ルーチン・メソッドのパラメーターとして、親のクラス型を定義して起き、実装時に引数としてはその親のオブジェクト識別子に子のオブジェクト参照をいれて引数としてルーチン・メソッドに渡せる

そして

* 親クラス型のオブジェクト識別子に入っている子クラスのオブジェクトのメソッドなどを使用する場合には、 `as ` キーワード(as演算子)を を使用して子クラス型のオブジェクトとして扱う

コード例を見てみましょう

```delphi
var
  myObject: TObject; //親クラス中の親、TObject型のオブジェクト識別子を宣言
  str : string;
begin
  myObject := TDate.Create; //TDateの参照は親クラスであるObject型のオブジェクト識別子に代入、保持できる
  try
    str := (myObject as TDate).Gettext; //myObjectをTDate型のオブジェクトとして、TdateのメソッドGetTextを使用
    // str := myObject.Gettext; //TObjectクラスはメソッドGetTextを持っていないので、これはコンパイル通らず
  finally
    myObject.Free;
  end;
end;
```

**このコードの例のポイント**

* すべてのクラスの親元 TObject型の オブジェクト識別子を`myObject`として宣言しています。
* TObject型オブジェクト識別子`myObject`に子クラスの`TData`クラスのオブジェクト参照を代入しています。（すべてのクラスは`TObject`から継承されています）
* TObject型オブジェクト識別子`myObject`に `as` キーワードを使って `TData`として取り扱うものとして、`myObject`に入っているTData型のオブジェクトの`GetText`メソッドを使用しています。
* `as` を使って TDataクラス型として使うことを明示しないと、宣言されている`TObject`クラス型の識別子では`TData`クラスが持っている`GetText`を持っていないため、コンパイルがとおりません

###**実は既に親オブジェクト識別子への子クラス参照の代入は使っています**
親のクラス型のオブジェクト識別子には、子のクラスのオブジェクト参照をいれられることを学んだところで、また便利な話をしておきます。
>※ちなみに子のクラス型のオブジェクト識別子には親のクラスのオブジェクト参照は入れられません。私はこのルールを個人的にカンガルー方式と呼んでいます。親のカンガルーの袋に子供は入るけど、逆はムリ。と。

便利な話に戻ります。

* イベントハンドラのパラメータの`TObject`クラスのオブジェクト識別子に、子クラスのオブジェクト参照が代入されている
* オブジェクト識別子に入っているクラスの型を判定する `is` キーワード(is演算子) が便利につかえる
* オブジェクト識別子を実際のクラスに合わせて使うには前ページの `as` を使うか、キャストする 
(例外として、この後に説明する `virtual` – `override` キーワードを使う方法はこの限りではない）

例としてボタンコンポーネントの`OnClick`イベントのイベントハンドラを見てみましょう。

```delphi
//Button1 の OnClickイベント
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Sender is TButton then //Senderオブジェクト識別子に入っているオブジェクトが TButtonか判定
  show(TButton(Sender).Text);//SenderをTButton型にキャストし、TButton型のTextプロパティを使用
// show(Sender.Text); //TObjectはTextプロパティを持っていないので、これはコンパイル通らず
end; 
```
**このコードのポイント**

* イベントハンドラで `Sender : TObject`をパラメータとして持っているイベントハンドラにおいて、`Sender : TObject`には、そのイベントを発生させている元となるコンポーネントのオブジェクト参照が入っています。この例ではボタンのオンクリックイベントなので、`Sender` オブジェクト識別子に、クリックされた `TButton`コンポーネントのオブジェクト参照が代入されています。
* `is` キーワードを使うことで、TObject型オブジェクト識別子の`Sender`に入っているオブジェクト参照がどんな型なのか確認することができます。ここでは `if Sender is TButton then ~ ` として `Sender`に入っているのが TButton型のオブジェクト参照なのか確認しています。
* そして`Sender`を使うときにはTButton型にキャストしています。 前のセクションで使っている `as`でもOKです。(キャストは第2回の「変数と型」で紹介している方法で、どの型に変化させるか型名を書き、その後ろに変化させたい変数などをカッコでくくて書く方法です）

###**親クラス型のオブジェクト識別子に子クラスの参照を入れる際に使えるキーワードとテクニック： virtual, abstract, override**
いよいよDelphi Starter Edition チュートリアルシリーズ シーズン2 の言語を覚えるシリーズも佳境です。（残る2回は「作ってみよう」の回となり、実際に一つのプログラムを作って試してみる回となります。）
このセクションでは親のオブジェクト識別子に子のオブジェクト参照を入れて使う際にキャストや `as`を使わずとも、動的に、代入されているオブジェクト参照が持っているメソッドを使用できるようになるテクニックをご紹介します。
実際にオブジェクト識別子に入っている参照のクラス型で実行されるメソッドが決定される方法を成し遂げるキーワードたちが `virtual`, `abstract`, `override` 三人衆です。

>オブジェクト識別子の中に実際に入っているオブジェクト参照に基づいて、オブジェクト参照が持っているメソッドの処理が実行されることを「遅延バインディング」と言ったりもします。ですが、この遅延バインディングといった呼び名はさほど重要ではないので覚えなくてもOKですが、プログラムの話をする時に現れる用語であったりします。その時に思い出す程度に覚えておいてあげても良いでしょう。（上から目線）

では、この `virtual`, `abstract`, `override` について、まずは説明します。

  \ 遅延バインディング三銃士をつれてきたよ！ /

* **virtual** : 親クラスのメソッド定義時に後方に付加しておくキーワード
 * 継承する子のクラスにて、当該メソッドが上書き(`override`)されることがあることを宣言しておくもの
 * 実行時にオブジェクト識別子に入っているクラス型によって実行するメソッドが変わる可能性があることを宣言している
 * 親のクラスで宣言しておくと、親クラス型のオブジェクト識別子に子クラス型のオブジェクトの参照が入っている時、子クラスのメソッドをキャストせず実行可能
 * `virtual`キーワードが付いていないと、オブジェクト識別子の宣言に使われたクラスのメソッドが実行される
<p></p><br>
* **abstract**: 親クラスのメソッド定義時に後方に付加しておくキーワード
  * メソッド定義時の親クラス内ではメソッドの実装をせず、子のクラスにおいて`override`で実装することを宣言しておくもの
  * `virtual`とセットで使う（`override`されることを前提としているキーワードなので）
  * このクラスを継承する子クラスにおいて`override`キーワードで処理を実装して使用する
  * 親オブジェクト識別子に子オブジェクト参照を入れて使うとき、親オブジェクト識別子で子クラスのメソッドを使うために宣言のみしておく
<p></p><br>
* **override**: 子のクラスのメソッド定義時に後方に付加するキーワード
  * 親クラスの`virtual`キーワードのついているメソッドを上書きすることを宣言するもの
  * 親クラスの`virtual`キーワードがついているメソッドの上書き時にのみ使用可能
  * 親オブジェクト識別子に、子オブジェクト参照を代入しているケースで、実行時に実際に代入されている子クラス型のメソッドが実行されるようになる
<p></p><br>

###**親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能・その使用テクニック**
それでは実際にどのようにしてキャストせずとも、親のオブジェクト識別子に、実際に代入されているオブジェクト参照に基づいたメソッドを実行させることができるのか見てみましょう。

####**下記のような親・子クラスの定義のモデルを例に説明**

![image](https://qiita-image-store.s3.amazonaws.com/0/145847/e01ff49e-14b4-3652-0fb6-efd710008ded.png)

####**typeブロックのコード例**
上記のモデルの定義部 `type`ブロックのコード例は下記のとおりです

```delphi
type
  // 親クラスとなるTKemonoクラス 定義
  TKemono = class(TObject) // TServel, TFennecの親クラス
  public
    function Voice: string; virtual; abstract;
    // Voice 文字列を返すメソッド。実装は子に任せるためvirtual; abstract; キーワードをつけている
  end;

  TServal = class(TKemono) // TKemonoを継承
  public
    function Voice: string; override;
    // 親クラス内のVoice 文字列を返すメソッド abstractのVoiceメソッド overrideするキーワード付き
  end;

  TFennec = class(TKemono) // TKemonoを継承
  public
    function Voice: string; override;
    // 親クラス内のVoice 文字列を返すメソッド abstractのVoiceメソッド overrideするキーワード付き
  end;
```
**このコードのポイント**

* モデル図どおりの親クラスとそれを継承した子クラスの定義です。
* 親クラスのメソッド`Voice`には、子のクラスにおいて上書きされ、動的に実行内容が判断される可能性があることを示す `virtual` キーワードが付加されています。そして、このクラスでは実装を行わず、実際に実装されるのは子のクラスにて行われることを示す `abstract` キーワードが付いています。
* 子クラスの`TServal`, `TFennec` クラスのいずれも親クラスと同名の`Voice`メソッドを持っています。親クラスで `virtual`キーワードが付加されて宣言されている `Voice`メソッドを 上書きして、動的に実行されるように `override`キーワードを付加しています

####**voiceメソッドの実装**
voiceメソッドの実装コードは下記のとおりです。

```delphi
implementation
{ TServal }
function TServal.Voice: string; //TServalのVoiceメソッド実装。実装部にはoverrideキーワードは不必要 
begin
  Result := 'meow'; //Voiceとして‘meow’文字列を返す
end;
{ TFennec }
function TFennec.Voice: string; //TFenncのVoiceメソッド実装。実装部にはoverrideキーワードは不必要  
begin
  Result := 'yelp'; //Voiceとして‘yelp’文字列を返す
end;
```
**このコードのポイント**

* 親クラスの `TKemono`クラスの `Voice`メソッドは 定義部で`abstract` キーワードを着けて当クラス（親クラス）内では実装しないよう定義していました。ですので、`TKemono`クラスの`Voice`メソッド実装の記述はありません。
* `TServal` と `TFennec`クラスの`Voice`メソッドがそれぞれ記述されています。実装部 `implementation`においては `override`キーワードを改めて記述する必要はありません。
* `TServal` クラスの `Voice`メソッドは 'meow'の文字列を、`TFennec`の`Voice`メソッドは'yelp'文字列を返すように実装されています。

####**使用コード例**
実際に使用してみるコード例がこちらです。

```delphi
procedure TForm1.Button2Click(Sender: TObject);
var
  myAnimal: TKemono; // 親クラスのオブジェクト識別子を宣言
begin
  if rbServal.IsChecked then // 選ばれているチェックボックスによって TServalかTFennecクラスのどちらかをCreate
    myAnimal := TServal.Create  // TServalのオブジェクト参照を親クラス型のオブジェクト識別子に代入
  else
    myAnimal := TFennec.Create; // TFennecのオブジェクト参照を親クラス型のオブジェクト識別子に代入
  try
    show(myAnimal.Voice); // 親の型のオブジェクト識別子に子のクラスのオブジェクト参照が代入されている
  finally
    myAnimal.Free; // 解放
  end;
end;
```
そしてこのコードを使ったサンプルコードを実行した結果のイメージショットがこちら
![image](https://qiita-image-store.s3.amazonaws.com/0/145847/fec3ddb1-6253-4426-ab14-a87288ed7dac.png)

**このコードとサンプルのポイント**

* 「なきごえ」ボタンが押されたとき、サーバル、フェネック、どちらのラジオボタンが選択されているかで、`TServal`, `TFennec` どちらかのオブジェクトを`Create`しています。
* `Create`したオブジェクトは`TKemono`(親クラス）型のオブジェクト識別子 `myAnimal` に代入しています
* 親クラスのオブジェクト識別子 + Voiceメソッド(`myAnimal.Voice`)で、キャストすることなく、代入されているオブジェクト参照の`Voice`メソッドが実行されます。
* このキャストすることなく、実際に代入されているオブジェクト参照に基づいたメソッドが実行されるようになるのは、以下の条件が揃えられているからでもあります。
    * 親のクラスが`Voice`メソッドを持っているため、`親のオブジェクト識別子.Voice` とコードを書いてもコンパイルできる
    * 親の`Voice`メソッドが`virtual` として、動的に実行メソッドが決められる方法が取られることを定義している
    * 子の`Voice`メソッドが`override` として、動的に実行メソッドが決められる方法が取られることを定義している 

###**さらに使えるメタクラス （ご参考）**
さらに、上のセクションで記述しているコードについて、クラスの`Create`を`if`文で分岐させず、`Create`をする部分をひとつにしてコードをクリアに記述したいような場合、どのクラスを使うのか、ルーチンに伝えて、別ルーチンで`Create`させる、といったこともできます。

* クラス型名を扱えるよう型を定義する : class of （実クラスのオブジェクト参照ではなく、クラスの型名そのものを渡せる）を使います
* 親のクラスの型名を型として宣言しておくと、メソッドのパラメータとしてクラスの型名（子のクラスの型名）を渡せる
* 渡された先のメソッドでクラスの型名からオブジェクトのインスタンスを作れる（Createできる）

まずは`type` ブロック

```delphi
type
TFriends = class of TKemono; // TKemonoクラスの型名を表す [TFriends]を定義
```
すでに TKemonoクラスは上のセクションで定義してあるものとして、ここでは新たに TKemonoクラスのクラス名を扱える型としてTFriendsクラス名型識別子を定義しています。なんだかわかりにくい表現ですが、`TKemono`, `TServal`, `TFennec`といったクラスを表す名を、このTFriends型は取り扱えるってことです。

次に、このTFriends をパラメータとして使って、新たなルーチンを実装したコード例です。

```delphi
function KemonoVoice(KemonoClassName: TFriends): String;
var
  myAnimal: TKemono;  //親クラスとなるTkemonoのオブジェクト識別子を宣言
begin
  myAnimal := KemonoClassName.Create; //パラメータで渡されたクラスの型（TServalかTFennec）をCreate
  try
    Result := myAnimal.Voice; //パラメータで渡されたクラス型でCreateしたオブジェクトのクラスメソッドを使用
  finally
    myAnimal.Free;	
  end;
end;
```
* パラメータとして使用されている `TFirends` 型の変数 `KemonoClassName`には、`TKemono`, `TServal`, `TFennec`といった`TKemono`クラスに属するクラス名を代入することができます。
* そしてコード内で行っている通り、そのクラス名が入っている`KemonoClassName`を使って、`KemonoClassName`に入っているクラス型のオブジェクトを`Create`することができます。
* `Create`したオブジェクト参照は、TKemono型のオブジェクト識別子に入れておきます。
* 先のセクションで行ったように、実際に入っているオブジェクト参照の型によって、実行されるメソッドが動的に決まり、１合致したクラスの`Voice`メソッドが実行されます。

ちなみに、この新たに作られた`KemonoVoice`ルーチンを呼び出しているコードがこちら。

* **ポイント** : 引数として、TServal や TFennec といったクラス名を渡しています。

```delphi
procedure TForm1.Button3Click(Sender: TObject);
begin
  if rbServal.IsChecked then
    show(KemonoVoice(TServal)) //クラスの型名 TServal を引数としてルーチンを実行
  else
    show(KemonoVoice(TFennec)); //クラスの型名 TFennec を引数としてルーチンを実行
end;
```
> より正確にいえば、「クラス名」を渡しているのではなく、クラスの型そのもののありかである参照（ポインタ・アドレス）を渡しています。
クラスの型そのものの参照を渡されたその先のルーチンで、クラスの型そのものの参照によって、クラスの型のありかにアクセスできるようになるので、そのクラスを使ってCreateしてオブジェクトとして確保することができる、といったことをやっています。

参考docWiki : http://docwiki.embarcadero.com/RADStudio/Seattle/ja/クラス参照
##おわりに

第7回、3月7日分の Delphiパート「オブジェクト指向」の、[その1](http://qiita.com/kazaiso/items/c76eac60bdd4dd075fa3)、その2 は以上です。
これにてシーズン2の 言語を学ぶ回は ひと段落となり、次回は学んだ言語を使って「作ってみよう」Delphiの部 になります。お楽しみに。

[＜＜シーズン２ 第6回の記事はこちら](http://qiita.com/kazaiso/items/b3941a234853b9cb6abb)
[シーズン２ 第8回の記事はこちら＞＞](http://qiita.com/mojeld/items/f5500a446fe9bd126184)