初歩的な質問かもしれませんが、フォーム内で関数を作成する場合
一般的に下記の①②③のどこに記述するのが良いのですか?
条件:同じアプリケーションの他のフォームから参照できる。
私の解釈の仕方は、
①はイベントプロシージャを記述する
②は自分で作成した関数を記述する
③はどういう時に使用するのかが良く分かりません。
宜しくお願いします。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure aaa(Sender: TObject); ←①published
private
{ Private 宣言 }
public
{ Public 宣言 }
procedure aaa(Sender: TObject); ←②public
end;
var
Form1: TForm1;
procedure aaa(Sender: TObject); ←③手続き/関数
implementation
{$R *.DFM}
procedure TForm1.aaa(Sender: TObject); ←③の場合は「TForm1.」 は記述しない
begin
end;
end.
位置に迷うのはOOPを理解してない証拠です。
①は IDE が自動で宣言する場所ですからダメ。
③は TForm1 クラスとの関連づけがないので論外。
②の位置かその上の private が「フォーム内で関数を作成する場合」の位置であって
迷う理由はほとんどありません。
どこに書いても一応どこからでも参照可能です。
1や2の場合はオブジェクトのメソッドとして使用できますので、Form1.aaa(args);などといって呼び出し可能です。
3の場合はグローバルな手続き/関数として使用できます。aaa(args); というように呼び出しできます。
1と2には、実行時情報が作成されるか否か(publishedは実行時に名前で参照するなどが可能だったはず、よく覚えてません)なので使う文にはかわりなしです。3はオブジェクトのメソッドじゃなくなるので、関数内でオブジェクトにアクセスしたりといったことが出来ません。
すべての関数、手続きがクラスのメンバである必要性も無いので、③もあり。
③の関数内でクラスのオブジェクト(TForm1、TEditなど)にアクセスしたい場合は、
Form1.Edit1.Text := 〜
のようにオブジェクト名を付けてアクセスすればいいだけのこと。
③の場合は、呼び出し元より前(上)に書いておけば一々宣言しなくても良いので便利でもある。
みなさん、返信ありがとうございます。
>①は IDE が自動で宣言する場所ですからダメ。
基本的には自分で作成した関数は②に記述しているのですが、たまに①に関数を記述してあるのを見かけるので何か理由があるのかなと思って質問しました。
ちなみに、①に自分で作成した関数を記述した場合、何か問題とかはあるのですか?
publishedでヘルプを調べてみると、「コンパイラにより実行時型情報が生成される。設計時は,オブジェクトインスペクタにパブリッシュプロパティが表示される。」
と書いてあるのですが、実行時型情報の意味が良く分かりません。
>3の場合はグローバルな手続き/関数として使用できます。aaa(args); というように呼び出しできます。
>3はオブジェクトのメソッドじゃなくなるので、関数内でオブジェクトにアクセスしたりといったことが出来ません。
③のメリットとしては、関数名の前にクラス名がいらないというのと、他のフォームから関数を呼び出す時に、オブジェクト名がいらない、ぐらいしか思いつかないのですが、絶対②ではなく③に記述しないといけない場合って
どんな時ですか?なかなか使う機会がないのですが・・・。
>③の場合は、呼び出し元より前(上)に書いておけば一々宣言しなくても良いので便利でもある。
ちょっと理解出来なかったのですが、もうちょっと具体的にお願い出来ますか?読解力がなくてすみません。
>ちなみに、①に自分で作成した関数を記述した場合、何か問題とかはあるのですか?
Button1Click等のイベントハンドラを作ったり消したりしたときに
不整合がおこっちゃったりする可能性がなきにしもあらずなので
①の部分には基本的に書いてはだめだと思っていてよいでしょう。
>たまに①に関数を記述してあるのを見かけるので
その書いた人も理解してなかったのでは,,,
私も人のソースみて、そういう時があって、
ぶち切れそうになりました。(ああ若かったなあの頃〜♪)
③は、クラスのメンバーじゃない関数がほしい時に使います。
procedure AAA(ALabel: TLabel);
begin
ALabel.Caption := 'テスト';
end;
と書いておいて
procedur TForm1.Button1Click(...);
begin
AAA(Self.Label1);
end;
や
procedur TForm1.Button2Click(...);
begin
AAA(Form2.Label1);
AAA(Form2.Label2);
end;
こんな記述をするとメリットが理解できるかな?
>③の場合は、呼び出し元より前(上)に書いておけば一々宣言しなくても良いので便利でもある。
procedure BBB(...
begin...end;
procedure TForm1.Button1Click(...
begin
BBB(...);
end;
とすればよくて
type
TForm1 = class(...
...
public
...
procedure CCC(...
end;
...
procedure TForm1.CCC(...
begin ... end;
proceudre TForm1.Button1Click(...
begin
CCC(...
end;
とするより、1行書く手間(TForm1の中身の1行)が省けるってことを意味している
んでしょうが、そういう意味のメリットはほとんどないと思います。
ま。OOP(=オブジェクト指向)を理解していない
ってのはその通りなので、そこらへんにより注意を向けて
勉強していくとスキルアップできるでしょう。
どこに書いても参照できる、ってことと正しく書くべきってことを区別すべきです。
汎用の関数は「フォーム内で関数を作成する場合」ではないので③はダメです。
①にも書けるってことと、書いていい、ってことは別です。
ほんとセンスが悪い人が多くて驚きます。
>たまに①に関数を記述してあるのを見かけるので
その書いた人も理解してなかったのでは,,,
今回の場合とは違うと思いますが、自分は、複数のコントロールのイベントに
同じイベントを割り当てしたいときに使います。
ここに書いておけば、オブジェクトインスペクタのイベント選択候補に上がってきますし、
メソッド内を空にしておけば、定義ごと削除されるという、通常のイベントのメソッドと
同じ効果になります。
> とするより、1行書く手間(TForm1の中身の1行)が省けるってことを意味している
> んでしょうが、そういう意味のメリットはほとんどないと思います。
別のユニットに公開したくない場合や、公開する必要がないような関数のときに使います。
ま、特別メリットになる話でもありませんが。
> ほんとセンスが悪い人が多くて驚きます。
これは、「自分以外はセンス悪いから困る」と、とられることもありますので
あまりおすすめできる表現ではないと思われます。
センスでなく、設計が問題ですね。
「フォーム内で関数を作成する場合」だと、抽象的すぎます。public,private,protectedもきちんと使い分ければ、(1)の位置に書くことはないでしょう。
他のモジュールから参照されたくない場合には、(1)も選びません。
また、派生クラスからのみ参照したい場合にも、(1)を選びません。
> 絶対②ではなく③に記述しないといけない場合って
API のコールバック関数とかWindow関数とかフック関数とかOSが型を決めている
関数はクラスのメソッドに出来ないので③でしか宣言できません。
みなさん、返信ありがとうございます。
みなさんのおかげで、どこに関数を記述すれば良いのか良く理解出来ました。
OOP(=オブジェクト指向)についてもっと勉強しなければいけないと実感しました。
ありがとうございました。
>OOP(=オブジェクト指向)についてもっと勉強しなければいけないと実感しました。
最適な参考書があります.購入して絶対と言うほど損はありません.
http://www.fukkan.com/vote.php3?no=4407
>最適な参考書があります.購入して絶対と言うほど損はありません.
ズバリ!! 今回の質問の内容と同様の解説が,最初の方のページにあります.
在庫数 在庫 なし
税込価格 \ 2,079 (本体1,980円+税)
申し訳ございませんが、現在ご注文いただけません。
ってなってるし・・・・
紀伊國屋にある
http://bookweb.kinokuniya.co.jp/htm/4774104272.html
ツイート | ![]() |