無料の開発環境 Delphi Starter Edition で Object Pascal 言語を優しく学ぶ 第4回 「Function と Procedure (関数と手続き）」

#Delphi Starter Edition チュートリアルシリーズ シーズン2 第4回 「Function と Procedure (関数と手続き）」
![image](https://qiita-image-store.s3.amazonaws.com/0/145847/4a72e369-3c63-1518-4b74-027780b3c5fb.png)

2017年1月23日より [「Delphi / C++Builder Starter チュートリアルシリーズ」 シーズン2、](http://forms.embarcadero.com/starter-tutorial-webinar)全9回、3月27日まで、毎週月曜日、Delphiパートが 17時00分~17時20分、 リアルタイム放送スペシャルコンテンツが5分～10分、C++Builderパートが 17時30分~17時50分の時間割でお送りしています。

無料でダウンロード & 利用できる開発環境の[Delphi / C++Builder Starter エディション](https://community.embarcadero.com/my-blog-posts?view=entry&id=8915)を使用して、プログラミング言語のDelphi (Object Pascal ), C++の基礎を学ぶオンラインセッションです。

##使用したスライドなどの情報を掲載します。
###Webセミナースライド
当セミナーのスライドは下記アドレスよりご参照いただけます。

http://www.slideshare.net/ssuser194f49/delphi-cbuilder-starter-2-delphi-4-function-procedure

###アジェンダ
* ねらい
 * 関数と手続きを知る
 * 関数と手続きの書き方
* 実施内容
  * functionとprocedure の違い
 * 宣言と実装
 * 使い方、関連するキーワード

###開発環境インストール
[Delphi / C++Builder Starter チュートリアルシリーズ](https://community.embarcadero.com/manage-blog-posts?view=entry&id=9038) シーズン1 第1回 ‟無料で始めよう アプリ作成„をご参考になり、開発環境をインストールしてください。

##**以下、Delphi Webセミナーの本筋**
###**function(関数)と procedure(手続き)**
* 名前（識別子）を付けて処理を実装しておき、その名前で呼び出せる
  * `function` : 関数。戻り値がある
  * `procedure` : 手続き。戻り値がない 
  * ルーチンという名称でひとくくりにすることもある
* 宣言の後には ` ; ` (セミコロン)
* 関数、手続きにデータを渡すには引数 として受け渡す
* 処理の実装部はルーチンの名称、パラメーター等の記述の後、`begin` で始まり`end;` で終わる 

###**implementation部での実装方法** 
* パラメーターがないときにパラメーターの記載のための( )は省略可
* `function` の戻り値は `Result` に代入

```delphi
procedure ルーチン識別子(パラメーターの識別子:パラメーターのデータ型);  // [;] を忘れずに
begin
  ShowMessage(str); //処理実装
end;

procedure ルーチン識別子;  //パラメーターがなければ(かっこ)省略可
begin
  //処理実装
end;

function ルーチン識別子(パラメーターの識別子:パラメーターのデータ型):戻り値のデータ型; 
begin
//戻り値があるfunctionはResultに戻り値を代入
  Result := 戻り値  //または関数名（ルーチン識別子）に戻り値を入れる
end;
```

###**functionと Procedure の 実装コード例**
```delphi
///コード例
procedure myShowProcedure(str: String);   //渡された文字列を表示するProcedure
begin
  ShowMessage(str);
end;

procedure Hello; //パラメータが必要なければ ( )は省略可
begin
  ShowMessage('Hello delphi world');
end;

function myIncFunction(I: Integer): Integer; //戻り値がある場合にはfunction
begin
  //パラメータ変数はは処理内で変数として使用可能
  Result := I + 1; //戻り値は Resultに代入
  // myIncFunction := I + 1; のように関数名に代入しても戻り値として返す
end;
```

###**ルーチンを呼出し順序を解決する「前方宣言」**
* 先に記述されているルーチンから、より後ろに記載されているルーチンを呼び出せません
* `forward` キーワードを付け、先に宣言しておき解決します
* 他ユニットから参照されて良い場合には`Interface`部で宣言してもよい

```delphi
procedure SayHi; forward; //forwardで実際の処理を記載せずに先に宣言のみ

procedure SayHiHi;
begin
  SayHi; //forwardキーワードで宣言しているため呼び出し可能
  SayHi;
end;

procedure SayHi; //forwardで実装を先送りにしてるルーチンの処理をここで記載
begin
  ShowMessage(‘はい’);
end;
```

###**クラス内に宣言されているルーチン「メソッド」**
* ※「クラス」の詳しくはオブジェクト指向のセッションで説明
* `Type`宣言で`TForm1`にくっついているイベントハンドラもメソッドの一つ

```delphi
//クラス TForm1のButton1Clickメソッド（イベントハンドラ）として実装しているコード例
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Tform内のOnclickメソッド における処理実装を記述
end;
```

**クラスに紐づいているルーチン「メソッド」の定義例**(詳しくは別セッションで説明予定）

```delphi
type //ブロックのクラス内で先にルーチンの宣言を行っておく
クラス名 = class(継承クラス)
procedure ルーチン識別子(パラメーター: パラメータのデータ型); //定義内でメソッド宣言のみ
//省略
end;

procedure クラス名.ルーチン名(パラメーター: パラメータのデータ型); //メソッドの実装
begin
  //省略
end;
```

###**自らのルーチンを呼び出すことが可能**
* 自らを呼び出すルーチン。「再起関数」と呼ばれる
* ループの代わりに使用したり、フォルダ階層の読み取りなどに使用

```delphi
function Ruijyou(Base, Exp: Integer): Integer; //BaseのExp累乗を求める再起関数
begin
  if Exp = 0 then
    begin
      Result := 1; 
    end
  else
    begin
      Result := Base * Ruijyou(Base, Exp - 1); //累乗数を減らして自らの関数を呼び出し
    end;
end;
```
この関数の呼び出し例 :

```delphi
I := Ruijyou(3, 3); //戻り値は27
```

###**ルーチンの処理をその場で終了しルーチンを出る「Exit」**
* ループ処理で必要な情報を見つけたときなどにその場でルーチンを終了できる
* `procedure` なら `Exit;` で ルーチンを出る
* `function_` なら `Exit(戻り値);` で戻り値を指定して出る

```delphi
//String に　‘A’が含まれているかチェックする関数
function CheckIncludeA(str: String): Boolean;
var
  ch: Char;
begin
  for ch in str do //for ループでstrの文字列の一文字を順にchに取り出して…
  begin
    if ch = 'A' then //chに'A'があるかチェック 
      begin
        Exit(True);    //Aを見つけたら戻り値TrueでループからExit（関数終了） 
      end; 
  end;
  Result := False; //Exitで終了せず、ここまで来てたら'A'はなかったものとしてFalse
end;
```

###**パラメータ と戻り値**
* ルーチンのパラメータと戻り値には定義されているデータ型と一致するデータを渡す（変数における代入と同じ）
* ルーチン使用時の引数（パラメータ）には式を使用可能

```delphi
function DoubleValue(iNum: Integer): Integer; //integer型のパラメータを持つ関数
begin
  Result := iNum * 2; //返す戻り値も整数を戻している（戻り値のInteger型と一致させている）
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I : Integer;
begin
 I := DoubleValue(8-1);    //式の結果、整数値なのでこれは定義と合致
 {I := DoubleValue(10.2); // 小数点の実数は定義の整数型と異なるので、これはエラーとなる}
end;
```

###**パラメータのデータ・変数の受け渡しについて**
* ルーチンでパラメータにデータを渡す方法は「**値渡し**」と「**参照渡し**」がある
* デフォルトでは**値渡し**
 * **値渡し**の場合、ルーチンの引数として呼び出し元でセットした変数は、呼び出し先のルーチン処理によって変更されない
 * 呼び出し先のルーチンでは引数は新たにコピーしてから使用される
* `var` キーワードを使用することによって**参照渡し**ができる
 * ルーチンの引数として呼び出しもとでセットした変数を、呼び出し先のルーチン内の処理によって変更できる
* パラメータの**値渡し**は、変数内の値だけを渡して、別途利用されるイメージ。**参照渡し**は、変数の入れ物ごと渡して変数に対して処理できるイメージ
* （例外）参照型と呼ばれるclassなどのオブジェクトは値渡しではない


###**パラメータのデータ・変数の受け渡しについて（２）**
* 参照渡しのコード例

```delphi
 procedure MyNameInput(var str: String); //参照渡しの varキーワードを変数識別子 strに付加
  begin
    str := 'Kaz Aiso'; //参照渡しなので、呼び出し元の変数に値を代入するのと同じ
  end;

  procedure TForm1.Button1Click(Sender: TObject);
  var
    myStr: string;
  begin
    MyNameInput(myStr); //呼び出しルーチンに値を代入してもらう
    ShowMessage(myStr); //参照渡しなので、変数に呼び出しルーチン先で文字列が入れられている.表示されるメッセージはKaz Aisoとなる
  end;
```

###**関数のオーバーロード**
* 同じルーチン識別子でパラメータ（と戻り値）の異なるルーチンを複数宣言・実装できる
* ルーチン宣言の後に`overload;`キーワードを記述
* パラメータに設定されたデータ型と、呼び出しの際の引数の型で判断して実行される
* 例 `AddFunc(10.1, 1.1);`  //浮動小数点の引数で下記関数を呼ぶと、2つ目のSingle型のパラメータを持った関数が実行される

```delphi
function AddFunc(A, B: Integer): Integer; overload; //整数値と整数値のパラメータ
begin
  Result := A + B;
end;

function AddFunc(A, B: Single): Single; overload; //浮動小数点と浮動小数点のパラメータ
begin
  Result := A + B;
end;

function AddFunc(A, B: Char): String; overload; //文字型と文字型のパラメータ
begin
  Result := A + B;
end;
```

###**他、関連する機能など**
より詳細な内容をご希望の方は下記のリンクなどをご参照ください。

* インライン化 (inline 指令)
  * コンパイル時に関数を、当該呼び出し箇所にインライン化
  * http://docwiki.embarcadero.com/RADStudio/Berlin/ja/手続きと関数の呼び出し（Delphi）
* 手続き型
  * ルーチンを型として使用する
  * http://docwiki.embarcadero.com/RADStudio/Berlin/ja/手続き型
* 外部宣言とDLL読み込み
  * http://docwiki.embarcadero.com/RADStudio/Berlin/ja/手続きと関数（Delphi）
  * http://docwiki.embarcadero.com/RADStudio/Berlin/ja/ライブラリとパッケージ

##おわりに
第4回 2月13日分の Delphiパート「Function と Procedure (関数と手続き）」は以上です。
[＜＜シーズン2 第3回の記事はこちら](http://qiita.com/kazaiso/items/93be0a3a000fabbea368)

[シーズン2 第5回の記事はこちら＞＞](http://qiita.com/kazaiso/items/3a648e9302cf27688b08)