DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

続きます。メソッド使える、高度なrecord型


      ブウォン
       {}    _____________
   ∧,,∧ {}   /
  ミ,,゚Д゚ミ|} <  ソースを使うのじゃ
   U  ,,Φ   \
 @ミ  ミ       ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ∪''∪ 



…それにしてもここっす、ここ。
Delphiテクニック - TStringListのシンプルな代替
http://dn.codegear.com/jp/article/33623

> TStringListを使うときに、いつもtry … finally ブロックを記述
> するのには、正直飽き飽きしてしまいました。もっと便利な方法が
> あったらいいのにとは思いませんか?

いや、そりゃ思いますよ。思います!大賛成だよ。

> 「高度なレコード型」を使いましょう。「高度なレコード型
> (Advanced Record)」は、従来の単純なレコード型に、メソッ
> ド、プロパティ、コンストラクタを追加したものです。

よーーし、いっちょやったりましょか。

> CreateやFreeを明示的に呼び出す必要がないのです。これにより、
> 次のようなコードが可能になります。
> var
>  list: TStringListRecord;
> begin
>  list.LoadFromFile('test.txt');
>  ...
> end;

ひゃーーー、カッコいーーー。
マヂィーかよーー!

で、どんどん読み進めていきましょう。


記事の中にある、Deleteの実装とかはどうでもいいっす。
パスです。動的配列のコントロールの説明は適当に読み流します。


> 問題なのは、Delphiでは、ローカル宣言される(レコード型を含
> む)大部分の変数は初期化されないということです。

オヨヨヨヨ?そういえば、そうなのね?

procedure TForm1.Button4Click(Sender: TObject);
var
 A: Integer;
begin
 ShowMessage(IntToStr(A));
end;
こんな不自然な事、Delphiじゃしないものね。
実行しても変な値がでます。

…そやけど、Aがクラスだったりしたら

var
 A: TStringList;
begin
 ShowMessage(IntToStr(A.Text));

ん??
Aには、プロパティがやまほどあるんですよ。
それぞれのプロパティは
Aの初期化処理が無いとまずいでしょ!

> ひとつの方法は、デフォルト値を設定するInitializeプ
> ロシージャをレコード型に追加することです。しかし、
> これは、TStringListRecordを使用するときに、必ず
> Initializeが呼び出されることをプログラマーが忘れな
> いようにしなければなりません。これはエラーを誘発し
> ます。

んん?そ…うかもしれんね…
暗黙で必要なメソッドがある。ことは
ちゃんと使う側が知っておかないとまずいだろうね。

> Itemsプロパティがうまく動作することを思い出してく
> ださい。これは、動的配列をローカル宣言したときに、
> Delphiが自動的に初期化するからです。これは必要に迫
> られて実行しています。

そして、
property CaseSensitive: boolean
が紹介されています。

ん?
Setの時に動的配列要素数を1にして?
Getの時は要素数1が存在してたらそれを返す?てる?

えーーー、これはないでしょーーよぅ!

こんな実装、、、ありえねーっしょ。
わっけわかんねーぞ、この実装!
function TStringListRecord.GetCaseSensitive: boolean;

デフォルト値は結局どっちなんだよ!
(記事の実装ではTrueのようですがすぐわかります?)

プロパティひとつ作ろうとする時、どんだけ苦労するんだよ!


んーーーー、継承はできないって制限があることはよくわかるけど
引数をとらないCreateを自分で実装できるようにしてくれよー。
なんだかなぁ。

ということで、漏れの中では
高度なrecord型を作りたくて使いたい場合
必要な場合は自分でinitializeメソッドを作ってしまった方がよい
そんな感じを受けました。

ばかばかしいややこしいプロパティ実装をしていくより
よっぽど実装が楽じゃないか?
ふざけた複雑さでプロパティ実装する間にバグが入るっつーの。


高度なrecord型の初期化には要注意、
constructor Create ではなんだかよくわからなくなるので
procedur Initialize;をメソッドとして作ってしまえばい。

…そんな感じ…かな?

しかし、この高度なrecord型のTStringListRecordを実装しようとして
内部にTStringListを利用しようとしたりすると、ですね。
initializeでTStringListをCreateするのはよいにしても
どこかで破棄コードをいれなければいけなくなるわけでしょう?

えっと、Finalizeも自作で作った方がよいの?

var
 sl: TStringListRecord;
begin
 sl.Initialize;
 sl.LoadFromFile(FileName);
 sl.Finalize;



   ∧,,∧l||l  それ、CreateとFreeが必要な
  ,ミ;゚Д゚彡  TStringListそのものと
  ミ  ∪つ    使い勝手
 ミ~,, ミ     ほとんどかわんなくなくない?
  ∪ ∪     

なくなくない?なくなくない?なくなくなくなくなくなくない?




さて、そういう意味で回避策も全然なく
いや、さて、どうしたものやら。
高度なrecord型。これ、結構使い方、限定されるよなあ。


以下、サンプルコード。

type
 TRecordTest1 = record
  Value: Integer;
 end;

procedure TForm1.Button5Click(Sender: TObject);
var
 rt: TRecordTest1;
begin
 ShowMessage(IntToStr(rt.Value));
end;
↑これは、初期化できてないので出力は変な値。

type
 TRecordTest2 = record
 private
  FValue: Integer;
  procedure SetValue(const Value: Integer);
  function GetValue: Integer;
 public
  property Value: Integer read GetValue write SetValue;
 end;

function TRecordTest2.GetValue: Integer;
begin
 Result := FValue;
end;

procedure TRecordTest2.SetValue(const Value: Integer);
begin
 FValue := Value;
end;

procedure TForm1.Button6Click(Sender: TObject);
var
 rt: TRecordTest2;
begin
 ShowMessage(IntToStr(rt.Value));
end;
↑これもやっぱり、初期化できてません

type
 TRecordTest3 = record
 private
  FValue: array of Integer;
  procedure SetValue(const Value: Integer);
  function GetValue: Integer;
 public
  property Value: Integer read GetValue write SetValue;
 end;

function TRecordTest3.GetValue: Integer;
begin
 if Length(FValue) = 1 then
 begin
  Result := FValue[0];
 end else
 begin
  Result := 0;
 end;
end;

procedure TRecordTest3.SetValue(const Value: Integer);
begin
 if Length(FValue) = 0 then
 begin
  SetLength(FValue, 1);
 end;
 FValue[0] := Value;
end;

procedure TForm1.Button7Click(Sender: TObject);
var
 rt: TRecordTest3;
begin
 ShowMessage(IntToStr(rt.Value));
end;
↑これなら、初期化されててデフォルト0が出力されるんだけど
ほんと、こんな実装を毎度するわけで?
面倒だ…

まあ、いいですけどね。
使い道をいろいろ悩んでみてみますけど。
高度なrecord型.....どこで使う?
スポンサーサイト

| 未分類 | 19:05 | comments:5 | trackbacks:0 | TOP↑

COMMENT

classじゃなくてobject宣言の旧クラスが帰ってきただけのような気がしてきたよ。

| 774 | 2008/01/23 19:37 | URL | ≫ EDIT

この分野に関しては、日本だと ytqwerty が一番詳しいと思う

|    | 2008/01/23 23:09 | URL | ≫ EDIT

> object宣言の旧クラスが

それは明日のネタだから、もちょっと内緒で!

| ミ・д・彡 | 2008/01/23 23:16 | URL | ≫ EDIT

http://twc.xrea.jp/
ここの1/25の記事見てみ
きっと驚くから

| plug and pray | 2008/01/26 03:43 | URL | ≫ EDIT

twcさんとこ紹介ありがとう。昨日から見つけてまして、読んでて、少しドキドキしてました。
record型が初期化処理いれられるのはとてもよいっすね。

まあ、通常の変数でも初期化処理を入れられる構文と、高度record型にコンストラクタデストラクタを自前で実装できるようになって欲しいです。

宣言とともにコンストラクタ、参照を過ぎるとデストラクタ呼ばれるとか。

そうしないと、高度レコード型の内部でTClassを内包しようとするのが事実上、不可能なので、記事の通り、Initialize,Finalizeを実装するのもかっこわるい、っすね。

| ミ・д・彡 | 2008/01/27 01:57 | URL | ≫ EDIT















非公開コメント

TRACKBACK URL

http://delfusa.blog65.fc2.com/tb.php/107-e21b15c3

TRACKBACK

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。