SlideShare a Scribd company logo
1 of 36
© 2016 Embarcadero Technologies, Inc.
All rights reserved. Proprietary and confidential.
第7回
‟オブジェクト指向„
シーズン2:プログラミング言語をやさしく覚えよう
DELPHIの部
2© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
Delphi / C++Builder Starter チュートリアルシリーズ
シーズン2 :2017年1月23日 ~ 3月27日 全 9 回
時間 :毎週 月曜 17 時 00分~17時 50分
Delphi 17時00分~17時20分 / C++Builder 17時30分~17時50分
ねらい :プログラミング言語をやさしく覚えよう
シーズン2
第1回 2017年1月23日 シューティングゲームのプログラム
第2回 1月30日 変数と 型
第3回 2月6日 条件 とループ
第4回 2月13日 Function と Procedure (関数と手続き)
第5回 2月20日 配列 と レコード
第6回 2月27日 文字列 と オブジェクト
第7回 3月6日 オブジェクト指向
第8回 3月13日 作ってみよう(1)
第9回 3月27日 作ってみよう(2)
セミナー情報 : 下記のWebサイト
http://forms.embarcadero.com/starter-tutorial-webinar
3© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
第7回 「オブジェクト指向」
 今日のねらい
• クラス・オブジェクトの機能を知る
• 隠蔽、継承を知る
 実施内容
• 隠蔽、継承とはどんなものか
• 隠蔽する方法
• 継承する方法
• まつわるあれこれ
4© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
無料版 Delphi 10.1 Berlin Starter Edition 入手方法
• シリアルキーを知らせるメール内にも再ダウンロードリンク有
エンバ
Web
製品 Delphi
Starter
バナー
登録 Get
 無料で使える開発環境をダウンロード
EDN*に登録済の方はEDNアカウントでダウンロード可
登録完了後、自動でインストーラーのダウンロード開始
インストール時にシリアルキーを入力
登録時のメールアドレスにシリアルキーが配信される
5© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
今日のチュートリアルで紹介しているサンプルコード
 GitHub からダウンロードして実際のコードを確認できます
 https://github.com/kazaiso/Starter_Tutorial_season2_20170306
6© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
クラスとオブジェクト
 クラス・オブジェクトとは
• 任意のデータ型(フィールド)を保持できる
• データにアクセス、処理するルーチン(メソッド)を持つ
• 独自のフィールドとメソッドを保持するための、ひとかたまり(クラス)
 データの隠蔽、クラスの継承ができる
• 他のユニットやクラスからフィールド・メソッドへのアクセス制限を行える
• 既存のクラスのフィールド・メソッドを保持しつつ、新しいフィールド・メソッドを追加した
新しいクラスを構築することができる
 クラスとオブジェクトの関係
• クラスとしてユーザー定義されたデータ型が「クラス」
• クラスの定義を使用するときの実体(インスタンス とも言います)が「オブジェクト」
• 今まで使用してきた「データ型」と「変数」の関係とほぼ同じ。 データ型を→ クラス ・変数→ オブジェクト
※前回のおさらい
7© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
var //varブロックでオブジェクト識別子宣言を行う
Birthday : TDate; {ここではオブジェクトの参照を保存するための識別子を宣言}
begin
Birthday := TDate.Create; {これでオブジェクトの実データ(インスタンス)を確
保}
Birthday.SetValue(1995, 2, 14);
//省略… Birthday.Free; メモリー(記憶領域)
オブジェクト識別子はオブジェクトの実体のある
「場所」を持っている
(オブジェクトの場所を「参照」している変数)
クラスの実体を保持する領域
(Createで確保される)
データの場所(アドレス)
オブジェクト
識別子
type //typeブロックでクラス定義を行う
TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義
procedure SetValue(Y, M, D: Integer); //クラスに紐づいたメソッド
function UruuDoshi: Boolean;
end; //クラス定義もend;で締める
type ブロック内で、フィールドやメソッドの定義をした
ひとかたまり、が「クラス」
オブジェクトの実体(インスタンス)は
クラス名.Create で確保
Create で確保されたオブジェクトを
参照する情報をオブジェクト識別子に代入
typeブロックで定義したクラスを実際に使うには、
varブロックでオブジェクトの変数識別子を宣言
※前回のおさらい
8© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
オブジェクト指向の便利さ
 クラス(設計図)
• すでにあるパーツの設計図、もしくは自ら作ったパーツの設計図を使って…
 オブジェクト(実体・インスタンス)
• 実際に部品を作り上げて使うことができる
 クラス継承
• すでにある設計図を基にカスタマイズを施して、使うこともできる
 ポリモーフィズム(多態性)・遅延バインド
• 作った部品の機能に基づいた結果をそれぞれ導き出せる
9© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
オブジェクト指向の便利さ… 実は既に使っています
 クラス(設計図)
• 最初に現れているForm1はクラス。
• クラスとしてTFormが作られているので…
 オブジェクト(実体・インスタンス)
• Form1としてすぐに使える
 クラス継承
• TFormがあるので、それを継承し、Form1を作って、それに様々コンポー
ネントを付加して、新たなForm1として設計しなおして利用している!
 ポリモーフィズム(多態性)・遅延バインド
• イベントハンドラで渡されている「Sender」などで利用(後ほど説明)
10© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
オブジェクト指向の便利さ… イメージ
設計図(TFormクラス)として作られているので…
すぐにフォーム(Form1)として使える
既存のTForm1を継承してカスタマイズして…
好みの機能を持ったForm1を作れる!
11© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
private, public , protected… 隠蔽と公開
 private, public , protected キーワードとは何か?
• 他ユニット上からのフィールドやメソッドのアクセスを制限、公開するためのキーワード
• private → 他ユニットからは参照できず、アクセスもできない
• public → 他ユニットから参照、アクセス可能
• protected → 他ユニットからは使用できない、当クラスを継承するクラスで参照・アクセス可能
 アクセス制限を行うと…
• 外部からフィールドをアクセスさせないことにより、直接参照されなくなる
• 将来的なコードの改変時に直接アクセスされない内部フィールドなどは、コード改変の影響が少ない
参考DocWiki:http://docwiki.embarcadero.com/RADStudio/Berlin/ja/クラスとオブジェクト(Delphi)
12© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
private, publicの使用例
 TDataクラスをprivate, publicを使って再び定義しなおしてみましょう
type //先週クラス定義した TDateクラスをprivate, pubicを使って再度定義
TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
private //privateキーワードで、他ユニットから参照されないように
Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義
public //publicキーワードで、他ユニットからでもアクセス可能に
procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド
function UruuDoshi: Boolean; //うるう年かチェックするメソッド
function GetText: string; //フィールドにアクセスできないので、日付を文字列で取得する関数追加
end; //クラス定義もend;で締める
type //先週のクラス定義を行う
TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義
procedure SetValue(Y, M, D: Integer); //クラスに紐づいたメソッド
function UruuDoshi: Boolean;
end; //クラス定義もend;で締める
先週のクラス定義(Private, pubicを使用していない class定義)
Private, pubicを使うように変更
13© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
private, public使用後の、フィールド変更例
 privateで指定しているフィールドを変更したい…
type //先週クラス定義した TDateクラスをprivate, pubicを使って再度定義
Tdate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
private //privateキーワードで、他ユニットから参照されないように
Year, Month, Day: Integer; //より便利なTDateTime型を使いたい…
public //publicキーワードで、他ユニットからでもアクセス可能に
procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド
function UruuDoshi: Boolean; //うるう年かチェックするメソッド
function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数追加
end; //クラス定義もend;で締める
type //typeブロックでクラス定義を行う
TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
private
FDate: TDateTime; //クラスで保持するデータ(フィールド)の定義
public
procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド
function UruuDoshi: Boolean; //うるう年かチェックするメソッド
function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数追加
end; //クラス定義もend;で締める
 TDateクラスのフィールドに、より便利なTDateTime型を使いたくなったら…
14© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
privateフィールド変更後のクラスメソッドの実装変更例
 private でアクセス制限をかけているフィールドは他ユニットから参照されていないので改変後もクラス内のみの
変更にとどまっており、Publicのルーチンやパラメータなど変更なく、他コードへの影響が少ない
procedure TDate.SetValue(Y, M, D: Integer); //フィールドTDateTime化に伴い実装変更
begin
//先週の旧実装 Year := Y; Month := M; Day := D;
FDate := EncodeDate(Y,M,D); //FDateフィールドに代入するように変更
end;
function TDate.Uruudoshi: Boolean; //フィールド変更に伴い実装変更
begin
//先週の旧実装 Result := IsLeapYear(Year);
Result := IsLeapYear(YearOf(Fdate)); //FDateから年情報を取り出してチェック
end;
function TDate.GetText: String; //フィールドにアクセス制限があるため、必要情報を提供する新規関数
begin
Result := DateToStr(FDate); //日付情報の文字列を提供
end;
15© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
クラスメソッド改変後の使用例(使用する側での変更なし)
procedure TForm1.Button1Click(Sender: TObject);
var //varブロックでオブジェクトの識別子宣言を行う
Birthday : TDate; {ここではオブジェクトの参照を保存するための識別子を宣言したのみ}
begin
Birthday := TDate.Create; {これでオブジェクトの実データ(インスタンス)を確保して、その参照をオブ
ジェクト識別子に代入した}
try
Birthday.SetValue(1995, 2, 14);
if Birthday.UruuDoshi then ShowMessage(‘うるうどしです')
else ShowMessage(‘うるうどしではない’);
finally
Birthday.Free; // これでオブジェクトのために確保したメモリを解放
end;
end;
 フィールドに直接アクセスしていなければ使用コード上も影響が少ない
 隠蔽と公開をしっかりわけておくことで、改変後の影響を少なくすることができる
 内部のフィールドの直接の書き換えを防ぐことで予期せぬ結果も防げる
16© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
クラスを使う上でのお約束 : try - finally
 例外(エラーが発生したとき)でも必ず処理すべきことを記述できる
• tryで例外処理範囲を開始
• 例外が発生しても、発生しなくても必ず処理する内容をfinally - end;で記述
 予期せぬ問題が起こった場合でもcreate確保した領域を解放して、リソースを保護
• もしかしたら、アプリケーションを継続できるかもしれない
• アプリを正常に終了できるようにしておけるかも
参考 DocWiki: http://docwiki.embarcadero.com/RADStudio/Berlin/ja/例外ハンドラの記述
begin
Birthday := TDate.Create; //オブジェクトをCreateしてオブジェクトの参照をオブジェクト識別子に代入
try //tryで例外発生の検知をセット
Birthday.SetValue(1995, 2, 14);
if Birthday.UruuDoshi then ShowMessage(‘うるうどしです')
else ShowMessage(‘うるうどしではありません’);
finally //try以降で例外が発生してもしなくても 必ず実行する処理を finally – end; に記述
Birthday.Free; //確保しているオブジェクトを解放
end; //finally のブロックはend; で閉じる
end;
17© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
初期処理・終了処理:コンストラクタ・デストラクタ
 コンストラクタ
• オブジェクト使用時に最初に初期化を行うために用意されているメソッド
• 通常、 Create として用意されている・用意する
 デストラクタ
• オブジェクト破棄(Free)前に実行されるために用意されるメソッド
• 通常 、Destroyとして用意されている・用意する
• Freeを実行すると、Destroyが実行されている
参考DocWiki : http://docwiki.embarcadero.com/RADStudio/Berlin/ja/メソッド(Delphi)
18© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
コンストラクタのCreate, デストラクタのDestroyの定義
type //typeブロックのクラス定義
TPerson = class //新たにTPersonクラスを定義
private
FName: string;
FBirthDay : TDate; //以前に定義した日付情報をもつTDateクラスをフィールドとして使用
public
constructor Create (name: string); //コンストラクター Create の宣言
destructor Destroy; override; //デストラクタ Destroyの宣言 + override
//そのほか必要なメソッド等…
end; //クラス定義end;
 コンストラクタはクラス内定義で constructor キーワードに続いて宣言
• コンストラクタは戻り値を宣言せずとも、確保したオブジェクトの参照を返してくれる
• すべてのデータが0に設定される(またはnil, 空文字列など、データ型に応じて)
• コンストラクタの主な目的は初期化、初期値の設定
 デストラクタはクラス内定義でdestructor キーワードに続いてDestroyメソッド宣言
• Freeを使ったときに呼び出される (宣言の後ろについている override は後ほど説明)
• デストラクタの主な目的なクリーンアップ
19© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
コンストラクタのCreate, デストラクタのDestroyの実装
Implementation
constructor TPerson.Create (name: string); //コンストラクター Create の実装
begin
inherited Create; //パラメータなしの親クラスのCreateを実行する
FName := name; //Create時の初期値としてフィールドに代入
FBirthDay := TDate.Create; //フィールドに使用しているTDate型のクラスの確保
end;
destructor TPerson.Destroy; //デストラクタ Destroyの宣言 (実装部に override キーワードは不要)
begin
FBirthDay.Free; //Create時に確保したFBirthDayの破棄
inherited; //何もついていないinheritedは、実装のメソッド名と全く同じメソッド名&パラメータの親メソッドを実行する
end;
 紐づいている クラス識別名.コンストラクタ定義識別子 (通常は Createで定義)で実装
• フィールドに特別な値を、初期値として入れたい場合はここで行う
• フィールドにクラスを使いたい場合には、ここでCreateしてオブジェクトを確保しておく
• inherited Create;: 継承した親クラスにある同名メソッド(コンストラクタ)を実施 (継承の説明は後ほど)
 紐づいている クラス識別名. デストラクタ定義識別子 (通常は Destroyで定義)で実装
• フィールドでクラスを使っている場合には、ここでFreeしておく
• inherited キーワードで継承した親クラスにある同名メソッド(デストラクタ)を実施 (継承の説明は後ほど)
20© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
同名メソッド、同名コンストラクタを作る 「overload」
 同じメソッド識別子名、またはコンストラクタ名で記述可能(第4回の関数と手続きの[overload]と同等)
• パラメータの内容でどのメソッド、コンストラクタを実行するか決定される
• 似たようなOverrideキーワードは後ほどの「継承」の時にご紹介
type //typeブロックでクラス定義
TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義
private
FDate : TDateTime; //クラスで保持するデータ(フィールド)の定義
public
Constructor Create; overload; //デフォルトのCreateと同じ記述でOverload指定
Constructor Create(Y, M, D: Integer); overload; //初期値を与えるCreateのoverload
procedure SetValue(Y, M, D: Integer); overload //年月日をIntegerでセットするメソッド
procedure SetValue(newDate: TDateTime); overload //年月日をTDateTimeでセットするメソッド
function UruuDoshi: Boolean; //うるう年かチェックするメソッド
function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数
end; //クラス定義もend;で締める
21© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
overload のCreate, SetValue実装例

implementation
{ TDate }
constructor TDate.Create; //実装部においてOverloadキーワードは記述不要
begin
inherited; //メソッド名もパラメータも同じであれば inherited の後ろのパラメータは省略可能
FDate := Date; //初期値としてDateで今日の日付を代入
end;
constructor TDate.Create(Y, M, D: Integer);//初期値有のCreate.実装部においてOverloadキーワードは記述不要
begin
inherited Create; {パラメータが親クラスのCreateと異なるので、省略できず、inheritedの後ろにCreateを記述して親の
Createを実行することを明記している}
FDate := EncodeDate(Y, M, D); //指定されたパラメータをTDateTime型に変換して初期値として代入
end;
procedure TDate.SetValue(Y, M, D: Integer); //Integer x 3の時実行.実装部においてOverloadキーワードは記述不要
begin
FDate := EncodeDate(Y, M, D); //指定されたパラメータをTDateTime型に変換してFDateフィールドに代入
end;
procedure TDate.SetValue(NewDate: TDateTime);//TDateTime型のパラメータの時実行.実装部にはOverloadキーワード不要
begin
FDate := NewDate;
end;
22© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
継承
 既にあるクラスのフィールドやメソッドを受け継いでクラス定義が可能
• 既存のクラスのフィールドやメソッドを受け継ぎつつ新たなフィールドやメソッドを追加したり、上書きすることが可能
• いずれ実装される子クラスに、メソッドの実装をゆだねておく、といった定義も可能
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;
type
子となるクラス定義識別子 = class(継承元となるクラス定義名)
public
//フィールド、メソッド…
23© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
継承先での新しいメソッドへの書き換え実装例
 継承先で新たな同名メソッドを記述して動作を変更することが可能
• 新クラスのオブジェクト識別子を使用した場合には、新クラスが持つメソッドの処理が行われる
• 親クラスのオブジェクト識別子を使用した場合には、親クラスが持つメソッドの処理が行われる
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;
24© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親クラスと子クラスのメソッド動作の違い
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;
 実際に親、子のクラスで持っている同名のメソッドを使ってみた結果
25© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
classを作ると、ある一つのクラスを継承している
 Delphi (Object Pascal) のclassはデフォルトで TObject クラスを自動的に継承
• type TDate = class の定義は type TDate = class(TObject) 定義と同じ
• すべてのクラスは基本的に TObject のサブクラス(子孫クラス)
 Create, Destroy, Free などは TObject で定義・実装されているメソッド
• コンストラクタの実装例で使用した inherited Create; は、TObject の Create を実行
• デストラクタの実装例で使用した inherited; は TObject の 同名の Destroy を実行
参考DocWiki: http://docwiki.embarcadero.com/Libraries/Berlin/ja/System.TObject
26© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
実は既に継承を使っています
 自動的に作成されたフォーム(TForm1)もクラスTFormを継承
{マルチデバイスアプリケーションを作成すると自動的に作られているForm1は、TFormクラスを継承したクラス識別子定義}
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ private 宣言 }
public
{ public 宣言 }
end;
27© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親・祖先のクラス型のオブジェクト識別子の下位互換性
 親・祖先のオブジェクト識別子に、子のクラス型のオブジェクト参照を代入可能
• ルーチン、メソッドのパラメーターとして、親のクラス型を定義し、実装時に引数として子のオブジェクト参照を渡せる
• 親クラス型のオブジェクト識別子に入っている子クラスのオブジェクトのメソッドなどを使用する場合には、
[ as ] を使用して子クラス型のオブジェクトとして扱える
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;
28© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
実は既に親オブジェクト識別子への子クラス参照の代入は使っています
 イベントハンドラのパラメータのTObjectクラスのオブジェクト識別子に、
子クラスのオブジェクト参照が代入されている
• オブジェクト識別子に入っているクラスの型を判定する [ is ] が便利につかえる
• オブジェクト識別子を実際のクラスに合わせて使うには前ページの[ as ] を使うか、キャストする
(例外として、この後に説明する virtual – override キーワードを使う方法はこの限りではない)
//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;
29© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親クラス型のオブジェクト識別子に子クラスの参照を入れる際に
使えるキーワードとテクニック: virtual, abstract, override
 virtual : 親クラスのメソッド定義時に後方に付加しておくキーワード
• 継承する子のクラスにて、当該メソッドが上書き(override)されることがあることを宣言しておくもの
• 実行時にオブジェクト識別子に入っているクラス型によって実行するメソッドが変わる可能性があることを宣言している
• 親のクラスで宣言しておくと、親クラス型のオブジェクト識別子に子クラス型のオブジェクトの参照が入っている時、
子クラスのメソッドをキャストせず実行可能
• virtualキーワードが付いていないと、オブジェクト識別子の宣言に使われたクラスのメソッドが実行される
 abstract: 親クラスのメソッド定義時に後方に付加しておくキーワード
• メソッド定義時の親クラス内ではメソッドの実装をせず、子のクラスにおいてoverrideで実装することを宣言しておくもの
• virtualとセットで使う(overrideされることを前提としているキーワードなので)
• このクラスを継承する子クラスにおいてoverrideキーワードで処理を実装して使用する
• 親オブジェクト識別子に子オブジェクト参照を入れて使うとき、親オブジェクト識別子で子クラスのメソッドを使うために宣言のみしておく
 override: 子のクラスのメソッド定義時に後方に付加するキーワード
• 親クラスのvirtualキーワードのついているメソッドを上書きすることを宣言するもの
• 親クラスのvirtualキーワードがついているメソッドの上書き時にのみ使用可能
• 親オブジェクト識別子に、子オブジェクト参照を代入しているケースで、実行時に実際に代入されている子クラス型のメソッドが実行されるようになる
30© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能
 継承元のオブジェクト識別子に、子のクラス型のオブジェクトを代入
• 下記のような親・子クラスの定義を例に説明
TKemono (親クラス)
function voice: string; virtual; abstract;
TServal (子クラス)
function voice: string; override;
TFennec (子クラス)
function voice: string; override;
function Tserval.voice: string;
begin
Result := ‘meow’;
end;
function Tfennec.voice: string;
begin
Result := ‘yelp’;
end;
TKemono型のオブジェクト識別子にTServalかTFennecの
オブジェクト参照を入れる
Voiceメソッドを実行すると、TKemono型オブジェクト識別子に
入っているTServalもしくは、TFennecのVoiceメソッドが
キャストせずとも、動的に判断され実行される
31© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能
 クラス定義
• 親クラス TKemono を定義 し、 子クラス TServal と Tfennec で継承
• 親クラスの Voiceメソッドは abstract キーワードを着けて実装はなし。 子クラスでそれぞれ override 実装してもらう
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;
32© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能
 子クラスのメソッド Voiceの実装
• override キーワードは実装部には必要なし
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;
33© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能
 使用例
• 「なきごえ」ボタンが押されたとき、サーバル、フェネック、どちらのラジオボタンが
選択されているかで、TServal, TFennec どちらかのオブジェクトをCreate
• CreateしたオブジェクトはTKemono(親クラス)型のオブジェクト識別子に代入
• 親クラスのオブジェクト識別子 + Voiceメソッドで、キャストするすることなく、代入
されているオブジェクトのVoiceメソッドが実行される
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;
34© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
さらに使えるメタクラス (ご参考)
 クラス型名を型として扱えるようにする : class of (実クラスのオブジェクト参照ではなく、クラスの型そのものを渡せる)
 親のクラスの型名を型として宣言しておくと、メソッドのパラメータとしてクラスの型名(子のクラスの型名)を渡せる
 渡された先のメソッドでクラスの型名からオブジェクトのインスタンスを作れる(Createできる)
type
TFriends = class of TKemono; // TKemonoクラスの型名を表す [TFriends]を定義
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;
procedure TForm1.Button3Click(Sender: TObject);
begin
if rbServal.IsChecked then
show(KemonoVoice(TServal)) //クラスの型名 TServal を引数としてルーチンを実行
else
show(KemonoVoice(TFennec)); //クラスの型名 TFennec を引数としてルーチンを実行
end;
35© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
本日のセミナー内容は
弊社ブログに掲載予定
[コミュニティ]
↓
[日本人ブログ]
実施内容の再視聴
 皆さんが見ているWebページの下に、順次アップロード
 エンバカデロWebサイト : http://forms.embarcadero.com/starter-tutorial-webinar
 [リソース] – [イベント]の「Delphi / C++Builder Starter チュートリアルシリーズ」ページ
 実施内容サマリー
• Community embarcadero (コミュニティ エンバカデロ)にWebリンク、サンプルコード情報等
http://community.embarcadero.com/
「エンバカデロ」で検索
36© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp
 次回は
3月13日(月)17:00より
“作ってみよう(1)„
Delphiの部
 このあと
• リアルタイム放送限定 特別コンテンツ
• C++ パート

More Related Content

Similar to 【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第7回 「オブジェクト指向 」

【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„和弘 井之上
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„Kaz Aiso
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„和弘 井之上
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„和弘 井之上
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„和弘 井之上
 
DelphiでWin/Macクロスコンパイル
DelphiでWin/MacクロスコンパイルDelphiでWin/Macクロスコンパイル
DelphiでWin/MacクロスコンパイルTomonori Ohba
 
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介Shintaro Hosoai
 
F#によるFunctional Programming入門
F#によるFunctional Programming入門F#によるFunctional Programming入門
F#によるFunctional Programming入門bleis tift
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„和弘 井之上
 
Eclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストEclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストAtsuhiro Kubo
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...Kaz Aiso
 
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会
.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会Kiyoshi Ogawa
 
openFrameworksセミナー(2014)レポート
openFrameworksセミナー(2014)レポートopenFrameworksセミナー(2014)レポート
openFrameworksセミナー(2014)レポートNariaki Iwatani
 
Room metro Tokyo #3 発表資料です。
Room metro Tokyo #3 発表資料です。Room metro Tokyo #3 発表資料です。
Room metro Tokyo #3 発表資料です。Manato KAMEYA
 
EclipseCon NA 2015 report
EclipseCon NA 2015 reportEclipseCon NA 2015 report
EclipseCon NA 2015 reportAkira Tanaka
 
I phoneアプリ入門 第5回
I phoneアプリ入門 第5回I phoneアプリ入門 第5回
I phoneアプリ入門 第5回Sachiko Kajishima
 
TechDo Goハンズオン#3
TechDo Goハンズオン#3TechDo Goハンズオン#3
TechDo Goハンズオン#3privatemy
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Uehara Junji
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/PrismNaoki Aoyama
 

Similar to 【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第7回 「オブジェクト指向 」 (20)

【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
 
DelphiでWin/Macクロスコンパイル
DelphiでWin/MacクロスコンパイルDelphiでWin/Macクロスコンパイル
DelphiでWin/Macクロスコンパイル
 
Xtext practice
Xtext practiceXtext practice
Xtext practice
 
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介
テキスト型Domain Specific Language (DSL) 開発フレームワークXtext の紹介
 
F#によるFunctional Programming入門
F#によるFunctional Programming入門F#によるFunctional Programming入門
F#によるFunctional Programming入門
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第7回 ‟オブジェクト指向„
 
Eclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストEclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテスト
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
 
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会
.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会
 
openFrameworksセミナー(2014)レポート
openFrameworksセミナー(2014)レポートopenFrameworksセミナー(2014)レポート
openFrameworksセミナー(2014)レポート
 
Room metro Tokyo #3 発表資料です。
Room metro Tokyo #3 発表資料です。Room metro Tokyo #3 発表資料です。
Room metro Tokyo #3 発表資料です。
 
EclipseCon NA 2015 report
EclipseCon NA 2015 reportEclipseCon NA 2015 report
EclipseCon NA 2015 report
 
I phoneアプリ入門 第5回
I phoneアプリ入門 第5回I phoneアプリ入門 第5回
I phoneアプリ入門 第5回
 
TechDo Goハンズオン#3
TechDo Goハンズオン#3TechDo Goハンズオン#3
TechDo Goハンズオン#3
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/Prism
 

More from Kaz Aiso

開発の現場でも役に立つボトプアップによるデータモデリング活用実例
開発の現場でも役に立つボトプアップによるデータモデリング活用実例開発の現場でも役に立つボトプアップによるデータモデリング活用実例
開発の現場でも役に立つボトプアップによるデータモデリング活用実例Kaz Aiso
 
ER/Studio データベース設計ツール
ER/Studio データベース設計ツールER/Studio データベース設計ツール
ER/Studio データベース設計ツールKaz Aiso
 
【U-22】Delphi / C++Builder / RAD Studio 概要
【U-22】Delphi / C++Builder / RAD Studio 概要【U-22】Delphi / C++Builder / RAD Studio 概要
【U-22】Delphi / C++Builder / RAD Studio 概要Kaz Aiso
 
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係Kaz Aiso
 
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)Kaz Aiso
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」Kaz Aiso
 
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップ
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップRAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップ
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップKaz Aiso
 
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを 移行ツールで最新化
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを移行ツールで最新化 Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを移行ツールで最新化
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを 移行ツールで最新化 Kaz Aiso
 
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」Kaz Aiso
 
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼう
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼうDELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼう
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼうKaz Aiso
 
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーション
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーションDELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーション
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーションKaz Aiso
 
移行セミナー BDE to FireDAC 20161018
移行セミナー BDE to  FireDAC 20161018移行セミナー BDE to  FireDAC 20161018
移行セミナー BDE to FireDAC 20161018Kaz Aiso
 

More from Kaz Aiso (12)

開発の現場でも役に立つボトプアップによるデータモデリング活用実例
開発の現場でも役に立つボトプアップによるデータモデリング活用実例開発の現場でも役に立つボトプアップによるデータモデリング活用実例
開発の現場でも役に立つボトプアップによるデータモデリング活用実例
 
ER/Studio データベース設計ツール
ER/Studio データベース設計ツールER/Studio データベース設計ツール
ER/Studio データベース設計ツール
 
【U-22】Delphi / C++Builder / RAD Studio 概要
【U-22】Delphi / C++Builder / RAD Studio 概要【U-22】Delphi / C++Builder / RAD Studio 概要
【U-22】Delphi / C++Builder / RAD Studio 概要
 
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係
データベースアプリケーション開発セミナー・最新のデータベースとアプリケーション開発の関係
 
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)
BDEを使った業務アプリを移行ツールで最新化(2017年4月14日開催)
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第5回 「配列 と レコード 」
 
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップ
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップRAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップ
RAD Studioで始めるマルチデバイス・クロスプラットフォーム開発ワークショップ
 
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを 移行ツールで最新化
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを移行ツールで最新化 Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを移行ツールで最新化
Delphi / C++Builder 業務アプリケーション 刷新実践法: BDEを使った業務アプリを 移行ツールで最新化
 
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」
Webセミナー「RAD Studio 10.1 Berlin Update 2 Anniversary Edition 新機能ガイド」
 
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼう
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼうDELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼう
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY2: DELPHIでUI設計のポイントを学ぼう
 
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーション
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーションDELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーション
DELPHI BOOT CAMP / DELPHIでビジュアル開発に挑戦しよう ◆ DAY1: Delphiで作るはじめてのアプリケーション
 
移行セミナー BDE to FireDAC 20161018
移行セミナー BDE to  FireDAC 20161018移行セミナー BDE to  FireDAC 20161018
移行セミナー BDE to FireDAC 20161018
 

【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第7回 「オブジェクト指向 」

  • 1. © 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. 第7回 ‟オブジェクト指向„ シーズン2:プログラミング言語をやさしく覚えよう DELPHIの部
  • 2. 2© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp Delphi / C++Builder Starter チュートリアルシリーズ シーズン2 :2017年1月23日 ~ 3月27日 全 9 回 時間 :毎週 月曜 17 時 00分~17時 50分 Delphi 17時00分~17時20分 / C++Builder 17時30分~17時50分 ねらい :プログラミング言語をやさしく覚えよう シーズン2 第1回 2017年1月23日 シューティングゲームのプログラム 第2回 1月30日 変数と 型 第3回 2月6日 条件 とループ 第4回 2月13日 Function と Procedure (関数と手続き) 第5回 2月20日 配列 と レコード 第6回 2月27日 文字列 と オブジェクト 第7回 3月6日 オブジェクト指向 第8回 3月13日 作ってみよう(1) 第9回 3月27日 作ってみよう(2) セミナー情報 : 下記のWebサイト http://forms.embarcadero.com/starter-tutorial-webinar
  • 3. 3© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 第7回 「オブジェクト指向」  今日のねらい • クラス・オブジェクトの機能を知る • 隠蔽、継承を知る  実施内容 • 隠蔽、継承とはどんなものか • 隠蔽する方法 • 継承する方法 • まつわるあれこれ
  • 4. 4© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 無料版 Delphi 10.1 Berlin Starter Edition 入手方法 • シリアルキーを知らせるメール内にも再ダウンロードリンク有 エンバ Web 製品 Delphi Starter バナー 登録 Get  無料で使える開発環境をダウンロード EDN*に登録済の方はEDNアカウントでダウンロード可 登録完了後、自動でインストーラーのダウンロード開始 インストール時にシリアルキーを入力 登録時のメールアドレスにシリアルキーが配信される
  • 5. 5© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 今日のチュートリアルで紹介しているサンプルコード  GitHub からダウンロードして実際のコードを確認できます  https://github.com/kazaiso/Starter_Tutorial_season2_20170306
  • 6. 6© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp クラスとオブジェクト  クラス・オブジェクトとは • 任意のデータ型(フィールド)を保持できる • データにアクセス、処理するルーチン(メソッド)を持つ • 独自のフィールドとメソッドを保持するための、ひとかたまり(クラス)  データの隠蔽、クラスの継承ができる • 他のユニットやクラスからフィールド・メソッドへのアクセス制限を行える • 既存のクラスのフィールド・メソッドを保持しつつ、新しいフィールド・メソッドを追加した 新しいクラスを構築することができる  クラスとオブジェクトの関係 • クラスとしてユーザー定義されたデータ型が「クラス」 • クラスの定義を使用するときの実体(インスタンス とも言います)が「オブジェクト」 • 今まで使用してきた「データ型」と「変数」の関係とほぼ同じ。 データ型を→ クラス ・変数→ オブジェクト ※前回のおさらい
  • 7. 7© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp var //varブロックでオブジェクト識別子宣言を行う Birthday : TDate; {ここではオブジェクトの参照を保存するための識別子を宣言} begin Birthday := TDate.Create; {これでオブジェクトの実データ(インスタンス)を確 保} Birthday.SetValue(1995, 2, 14); //省略… Birthday.Free; メモリー(記憶領域) オブジェクト識別子はオブジェクトの実体のある 「場所」を持っている (オブジェクトの場所を「参照」している変数) クラスの実体を保持する領域 (Createで確保される) データの場所(アドレス) オブジェクト 識別子 type //typeブロックでクラス定義を行う TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義 procedure SetValue(Y, M, D: Integer); //クラスに紐づいたメソッド function UruuDoshi: Boolean; end; //クラス定義もend;で締める type ブロック内で、フィールドやメソッドの定義をした ひとかたまり、が「クラス」 オブジェクトの実体(インスタンス)は クラス名.Create で確保 Create で確保されたオブジェクトを 参照する情報をオブジェクト識別子に代入 typeブロックで定義したクラスを実際に使うには、 varブロックでオブジェクトの変数識別子を宣言 ※前回のおさらい
  • 8. 8© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp オブジェクト指向の便利さ  クラス(設計図) • すでにあるパーツの設計図、もしくは自ら作ったパーツの設計図を使って…  オブジェクト(実体・インスタンス) • 実際に部品を作り上げて使うことができる  クラス継承 • すでにある設計図を基にカスタマイズを施して、使うこともできる  ポリモーフィズム(多態性)・遅延バインド • 作った部品の機能に基づいた結果をそれぞれ導き出せる
  • 9. 9© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp オブジェクト指向の便利さ… 実は既に使っています  クラス(設計図) • 最初に現れているForm1はクラス。 • クラスとしてTFormが作られているので…  オブジェクト(実体・インスタンス) • Form1としてすぐに使える  クラス継承 • TFormがあるので、それを継承し、Form1を作って、それに様々コンポー ネントを付加して、新たなForm1として設計しなおして利用している!  ポリモーフィズム(多態性)・遅延バインド • イベントハンドラで渡されている「Sender」などで利用(後ほど説明)
  • 10. 10© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp オブジェクト指向の便利さ… イメージ 設計図(TFormクラス)として作られているので… すぐにフォーム(Form1)として使える 既存のTForm1を継承してカスタマイズして… 好みの機能を持ったForm1を作れる!
  • 11. 11© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp private, public , protected… 隠蔽と公開  private, public , protected キーワードとは何か? • 他ユニット上からのフィールドやメソッドのアクセスを制限、公開するためのキーワード • private → 他ユニットからは参照できず、アクセスもできない • public → 他ユニットから参照、アクセス可能 • protected → 他ユニットからは使用できない、当クラスを継承するクラスで参照・アクセス可能  アクセス制限を行うと… • 外部からフィールドをアクセスさせないことにより、直接参照されなくなる • 将来的なコードの改変時に直接アクセスされない内部フィールドなどは、コード改変の影響が少ない 参考DocWiki:http://docwiki.embarcadero.com/RADStudio/Berlin/ja/クラスとオブジェクト(Delphi)
  • 12. 12© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp private, publicの使用例  TDataクラスをprivate, publicを使って再び定義しなおしてみましょう type //先週クラス定義した TDateクラスをprivate, pubicを使って再度定義 TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 private //privateキーワードで、他ユニットから参照されないように Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義 public //publicキーワードで、他ユニットからでもアクセス可能に procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド function UruuDoshi: Boolean; //うるう年かチェックするメソッド function GetText: string; //フィールドにアクセスできないので、日付を文字列で取得する関数追加 end; //クラス定義もend;で締める type //先週のクラス定義を行う TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 Year, Month, Day: Integer; //クラスで保持するデータ(フィールド)の定義 procedure SetValue(Y, M, D: Integer); //クラスに紐づいたメソッド function UruuDoshi: Boolean; end; //クラス定義もend;で締める 先週のクラス定義(Private, pubicを使用していない class定義) Private, pubicを使うように変更
  • 13. 13© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp private, public使用後の、フィールド変更例  privateで指定しているフィールドを変更したい… type //先週クラス定義した TDateクラスをprivate, pubicを使って再度定義 Tdate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 private //privateキーワードで、他ユニットから参照されないように Year, Month, Day: Integer; //より便利なTDateTime型を使いたい… public //publicキーワードで、他ユニットからでもアクセス可能に procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド function UruuDoshi: Boolean; //うるう年かチェックするメソッド function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数追加 end; //クラス定義もend;で締める type //typeブロックでクラス定義を行う TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 private FDate: TDateTime; //クラスで保持するデータ(フィールド)の定義 public procedure SetValue(Y, M, D: Integer); // 年月日をセットするメソッド function UruuDoshi: Boolean; //うるう年かチェックするメソッド function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数追加 end; //クラス定義もend;で締める  TDateクラスのフィールドに、より便利なTDateTime型を使いたくなったら…
  • 14. 14© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp privateフィールド変更後のクラスメソッドの実装変更例  private でアクセス制限をかけているフィールドは他ユニットから参照されていないので改変後もクラス内のみの 変更にとどまっており、Publicのルーチンやパラメータなど変更なく、他コードへの影響が少ない procedure TDate.SetValue(Y, M, D: Integer); //フィールドTDateTime化に伴い実装変更 begin //先週の旧実装 Year := Y; Month := M; Day := D; FDate := EncodeDate(Y,M,D); //FDateフィールドに代入するように変更 end; function TDate.Uruudoshi: Boolean; //フィールド変更に伴い実装変更 begin //先週の旧実装 Result := IsLeapYear(Year); Result := IsLeapYear(YearOf(Fdate)); //FDateから年情報を取り出してチェック end; function TDate.GetText: String; //フィールドにアクセス制限があるため、必要情報を提供する新規関数 begin Result := DateToStr(FDate); //日付情報の文字列を提供 end;
  • 15. 15© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp クラスメソッド改変後の使用例(使用する側での変更なし) procedure TForm1.Button1Click(Sender: TObject); var //varブロックでオブジェクトの識別子宣言を行う Birthday : TDate; {ここではオブジェクトの参照を保存するための識別子を宣言したのみ} begin Birthday := TDate.Create; {これでオブジェクトの実データ(インスタンス)を確保して、その参照をオブ ジェクト識別子に代入した} try Birthday.SetValue(1995, 2, 14); if Birthday.UruuDoshi then ShowMessage(‘うるうどしです') else ShowMessage(‘うるうどしではない’); finally Birthday.Free; // これでオブジェクトのために確保したメモリを解放 end; end;  フィールドに直接アクセスしていなければ使用コード上も影響が少ない  隠蔽と公開をしっかりわけておくことで、改変後の影響を少なくすることができる  内部のフィールドの直接の書き換えを防ぐことで予期せぬ結果も防げる
  • 16. 16© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp クラスを使う上でのお約束 : try - finally  例外(エラーが発生したとき)でも必ず処理すべきことを記述できる • tryで例外処理範囲を開始 • 例外が発生しても、発生しなくても必ず処理する内容をfinally - end;で記述  予期せぬ問題が起こった場合でもcreate確保した領域を解放して、リソースを保護 • もしかしたら、アプリケーションを継続できるかもしれない • アプリを正常に終了できるようにしておけるかも 参考 DocWiki: http://docwiki.embarcadero.com/RADStudio/Berlin/ja/例外ハンドラの記述 begin Birthday := TDate.Create; //オブジェクトをCreateしてオブジェクトの参照をオブジェクト識別子に代入 try //tryで例外発生の検知をセット Birthday.SetValue(1995, 2, 14); if Birthday.UruuDoshi then ShowMessage(‘うるうどしです') else ShowMessage(‘うるうどしではありません’); finally //try以降で例外が発生してもしなくても 必ず実行する処理を finally – end; に記述 Birthday.Free; //確保しているオブジェクトを解放 end; //finally のブロックはend; で閉じる end;
  • 17. 17© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 初期処理・終了処理:コンストラクタ・デストラクタ  コンストラクタ • オブジェクト使用時に最初に初期化を行うために用意されているメソッド • 通常、 Create として用意されている・用意する  デストラクタ • オブジェクト破棄(Free)前に実行されるために用意されるメソッド • 通常 、Destroyとして用意されている・用意する • Freeを実行すると、Destroyが実行されている 参考DocWiki : http://docwiki.embarcadero.com/RADStudio/Berlin/ja/メソッド(Delphi)
  • 18. 18© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp コンストラクタのCreate, デストラクタのDestroyの定義 type //typeブロックのクラス定義 TPerson = class //新たにTPersonクラスを定義 private FName: string; FBirthDay : TDate; //以前に定義した日付情報をもつTDateクラスをフィールドとして使用 public constructor Create (name: string); //コンストラクター Create の宣言 destructor Destroy; override; //デストラクタ Destroyの宣言 + override //そのほか必要なメソッド等… end; //クラス定義end;  コンストラクタはクラス内定義で constructor キーワードに続いて宣言 • コンストラクタは戻り値を宣言せずとも、確保したオブジェクトの参照を返してくれる • すべてのデータが0に設定される(またはnil, 空文字列など、データ型に応じて) • コンストラクタの主な目的は初期化、初期値の設定  デストラクタはクラス内定義でdestructor キーワードに続いてDestroyメソッド宣言 • Freeを使ったときに呼び出される (宣言の後ろについている override は後ほど説明) • デストラクタの主な目的なクリーンアップ
  • 19. 19© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp コンストラクタのCreate, デストラクタのDestroyの実装 Implementation constructor TPerson.Create (name: string); //コンストラクター Create の実装 begin inherited Create; //パラメータなしの親クラスのCreateを実行する FName := name; //Create時の初期値としてフィールドに代入 FBirthDay := TDate.Create; //フィールドに使用しているTDate型のクラスの確保 end; destructor TPerson.Destroy; //デストラクタ Destroyの宣言 (実装部に override キーワードは不要) begin FBirthDay.Free; //Create時に確保したFBirthDayの破棄 inherited; //何もついていないinheritedは、実装のメソッド名と全く同じメソッド名&パラメータの親メソッドを実行する end;  紐づいている クラス識別名.コンストラクタ定義識別子 (通常は Createで定義)で実装 • フィールドに特別な値を、初期値として入れたい場合はここで行う • フィールドにクラスを使いたい場合には、ここでCreateしてオブジェクトを確保しておく • inherited Create;: 継承した親クラスにある同名メソッド(コンストラクタ)を実施 (継承の説明は後ほど)  紐づいている クラス識別名. デストラクタ定義識別子 (通常は Destroyで定義)で実装 • フィールドでクラスを使っている場合には、ここでFreeしておく • inherited キーワードで継承した親クラスにある同名メソッド(デストラクタ)を実施 (継承の説明は後ほど)
  • 20. 20© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 同名メソッド、同名コンストラクタを作る 「overload」  同じメソッド識別子名、またはコンストラクタ名で記述可能(第4回の関数と手続きの[overload]と同等) • パラメータの内容でどのメソッド、コンストラクタを実行するか決定される • 似たようなOverrideキーワードは後ほどの「継承」の時にご紹介 type //typeブロックでクラス定義 TDate = class //TDateというクラス定義識別子を、「 = class 」としてクラス定義 private FDate : TDateTime; //クラスで保持するデータ(フィールド)の定義 public Constructor Create; overload; //デフォルトのCreateと同じ記述でOverload指定 Constructor Create(Y, M, D: Integer); overload; //初期値を与えるCreateのoverload procedure SetValue(Y, M, D: Integer); overload //年月日をIntegerでセットするメソッド procedure SetValue(newDate: TDateTime); overload //年月日をTDateTimeでセットするメソッド function UruuDoshi: Boolean; //うるう年かチェックするメソッド function GetText: String; //フィールドにアクセスできないので、日付を文字列で取得する関数 end; //クラス定義もend;で締める
  • 21. 21© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp overload のCreate, SetValue実装例  implementation { TDate } constructor TDate.Create; //実装部においてOverloadキーワードは記述不要 begin inherited; //メソッド名もパラメータも同じであれば inherited の後ろのパラメータは省略可能 FDate := Date; //初期値としてDateで今日の日付を代入 end; constructor TDate.Create(Y, M, D: Integer);//初期値有のCreate.実装部においてOverloadキーワードは記述不要 begin inherited Create; {パラメータが親クラスのCreateと異なるので、省略できず、inheritedの後ろにCreateを記述して親の Createを実行することを明記している} FDate := EncodeDate(Y, M, D); //指定されたパラメータをTDateTime型に変換して初期値として代入 end; procedure TDate.SetValue(Y, M, D: Integer); //Integer x 3の時実行.実装部においてOverloadキーワードは記述不要 begin FDate := EncodeDate(Y, M, D); //指定されたパラメータをTDateTime型に変換してFDateフィールドに代入 end; procedure TDate.SetValue(NewDate: TDateTime);//TDateTime型のパラメータの時実行.実装部にはOverloadキーワード不要 begin FDate := NewDate; end;
  • 22. 22© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 継承  既にあるクラスのフィールドやメソッドを受け継いでクラス定義が可能 • 既存のクラスのフィールドやメソッドを受け継ぎつつ新たなフィールドやメソッドを追加したり、上書きすることが可能 • いずれ実装される子クラスに、メソッドの実装をゆだねておく、といった定義も可能 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; type 子となるクラス定義識別子 = class(継承元となるクラス定義名) public //フィールド、メソッド…
  • 23. 23© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 継承先での新しいメソッドへの書き換え実装例  継承先で新たな同名メソッドを記述して動作を変更することが可能 • 新クラスのオブジェクト識別子を使用した場合には、新クラスが持つメソッドの処理が行われる • 親クラスのオブジェクト識別子を使用した場合には、親クラスが持つメソッドの処理が行われる 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;
  • 24. 24© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親クラスと子クラスのメソッド動作の違い 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;  実際に親、子のクラスで持っている同名のメソッドを使ってみた結果
  • 25. 25© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp classを作ると、ある一つのクラスを継承している  Delphi (Object Pascal) のclassはデフォルトで TObject クラスを自動的に継承 • type TDate = class の定義は type TDate = class(TObject) 定義と同じ • すべてのクラスは基本的に TObject のサブクラス(子孫クラス)  Create, Destroy, Free などは TObject で定義・実装されているメソッド • コンストラクタの実装例で使用した inherited Create; は、TObject の Create を実行 • デストラクタの実装例で使用した inherited; は TObject の 同名の Destroy を実行 参考DocWiki: http://docwiki.embarcadero.com/Libraries/Berlin/ja/System.TObject
  • 26. 26© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 実は既に継承を使っています  自動的に作成されたフォーム(TForm1)もクラスTFormを継承 {マルチデバイスアプリケーションを作成すると自動的に作られているForm1は、TFormクラスを継承したクラス識別子定義} type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { private 宣言 } public { public 宣言 } end;
  • 27. 27© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親・祖先のクラス型のオブジェクト識別子の下位互換性  親・祖先のオブジェクト識別子に、子のクラス型のオブジェクト参照を代入可能 • ルーチン、メソッドのパラメーターとして、親のクラス型を定義し、実装時に引数として子のオブジェクト参照を渡せる • 親クラス型のオブジェクト識別子に入っている子クラスのオブジェクトのメソッドなどを使用する場合には、 [ as ] を使用して子クラス型のオブジェクトとして扱える 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;
  • 28. 28© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 実は既に親オブジェクト識別子への子クラス参照の代入は使っています  イベントハンドラのパラメータのTObjectクラスのオブジェクト識別子に、 子クラスのオブジェクト参照が代入されている • オブジェクト識別子に入っているクラスの型を判定する [ is ] が便利につかえる • オブジェクト識別子を実際のクラスに合わせて使うには前ページの[ as ] を使うか、キャストする (例外として、この後に説明する virtual – override キーワードを使う方法はこの限りではない) //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;
  • 29. 29© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親クラス型のオブジェクト識別子に子クラスの参照を入れる際に 使えるキーワードとテクニック: virtual, abstract, override  virtual : 親クラスのメソッド定義時に後方に付加しておくキーワード • 継承する子のクラスにて、当該メソッドが上書き(override)されることがあることを宣言しておくもの • 実行時にオブジェクト識別子に入っているクラス型によって実行するメソッドが変わる可能性があることを宣言している • 親のクラスで宣言しておくと、親クラス型のオブジェクト識別子に子クラス型のオブジェクトの参照が入っている時、 子クラスのメソッドをキャストせず実行可能 • virtualキーワードが付いていないと、オブジェクト識別子の宣言に使われたクラスのメソッドが実行される  abstract: 親クラスのメソッド定義時に後方に付加しておくキーワード • メソッド定義時の親クラス内ではメソッドの実装をせず、子のクラスにおいてoverrideで実装することを宣言しておくもの • virtualとセットで使う(overrideされることを前提としているキーワードなので) • このクラスを継承する子クラスにおいてoverrideキーワードで処理を実装して使用する • 親オブジェクト識別子に子オブジェクト参照を入れて使うとき、親オブジェクト識別子で子クラスのメソッドを使うために宣言のみしておく  override: 子のクラスのメソッド定義時に後方に付加するキーワード • 親クラスのvirtualキーワードのついているメソッドを上書きすることを宣言するもの • 親クラスのvirtualキーワードがついているメソッドの上書き時にのみ使用可能 • 親オブジェクト識別子に、子オブジェクト参照を代入しているケースで、実行時に実際に代入されている子クラス型のメソッドが実行されるようになる
  • 30. 30© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能  継承元のオブジェクト識別子に、子のクラス型のオブジェクトを代入 • 下記のような親・子クラスの定義を例に説明 TKemono (親クラス) function voice: string; virtual; abstract; TServal (子クラス) function voice: string; override; TFennec (子クラス) function voice: string; override; function Tserval.voice: string; begin Result := ‘meow’; end; function Tfennec.voice: string; begin Result := ‘yelp’; end; TKemono型のオブジェクト識別子にTServalかTFennecの オブジェクト参照を入れる Voiceメソッドを実行すると、TKemono型オブジェクト識別子に 入っているTServalもしくは、TFennecのVoiceメソッドが キャストせずとも、動的に判断され実行される
  • 31. 31© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能  クラス定義 • 親クラス TKemono を定義 し、 子クラス TServal と Tfennec で継承 • 親クラスの Voiceメソッドは abstract キーワードを着けて実装はなし。 子クラスでそれぞれ override 実装してもらう 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;
  • 32. 32© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能  子クラスのメソッド Voiceの実装 • override キーワードは実装部には必要なし 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;
  • 33. 33© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 親、祖先のオブジェクト識別子に子オブジェクト参照を代入可能  使用例 • 「なきごえ」ボタンが押されたとき、サーバル、フェネック、どちらのラジオボタンが 選択されているかで、TServal, TFennec どちらかのオブジェクトをCreate • CreateしたオブジェクトはTKemono(親クラス)型のオブジェクト識別子に代入 • 親クラスのオブジェクト識別子 + Voiceメソッドで、キャストするすることなく、代入 されているオブジェクトのVoiceメソッドが実行される 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;
  • 34. 34© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp さらに使えるメタクラス (ご参考)  クラス型名を型として扱えるようにする : class of (実クラスのオブジェクト参照ではなく、クラスの型そのものを渡せる)  親のクラスの型名を型として宣言しておくと、メソッドのパラメータとしてクラスの型名(子のクラスの型名)を渡せる  渡された先のメソッドでクラスの型名からオブジェクトのインスタンスを作れる(Createできる) type TFriends = class of TKemono; // TKemonoクラスの型名を表す [TFriends]を定義 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; procedure TForm1.Button3Click(Sender: TObject); begin if rbServal.IsChecked then show(KemonoVoice(TServal)) //クラスの型名 TServal を引数としてルーチンを実行 else show(KemonoVoice(TFennec)); //クラスの型名 TFennec を引数としてルーチンを実行 end;
  • 35. 35© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp 本日のセミナー内容は 弊社ブログに掲載予定 [コミュニティ] ↓ [日本人ブログ] 実施内容の再視聴  皆さんが見ているWebページの下に、順次アップロード  エンバカデロWebサイト : http://forms.embarcadero.com/starter-tutorial-webinar  [リソース] – [イベント]の「Delphi / C++Builder Starter チュートリアルシリーズ」ページ  実施内容サマリー • Community embarcadero (コミュニティ エンバカデロ)にWebリンク、サンプルコード情報等 http://community.embarcadero.com/ 「エンバカデロ」で検索
  • 36. 36© 2016 Embarcadero Technologies, Inc. All rights reserved. Proprietary and confidential. #embtwebi_jp  次回は 3月13日(月)17:00より “作ってみよう(1)„ Delphiの部  このあと • リアルタイム放送限定 特別コンテンツ • C++ パート