鳥の巣箱

ネトゲしたり、機械いじったり、ソフト書いたり、山篭ったり、ギャンブルしたりする人

自作クラス作成Tips ー 自作クラスにレコード型のプロパティを持たせる時の注意

自作クラスにレコードプロパティを実装したいという場面は結構あるはずです。
ただ、実装時にはいくつか注意しなければならないことがあります。

レコードプロパティのメンバに代入するときの問題

例えば次のような実装の時

  TTsrRec = record
    Name  : string;
    No    : Integer;
  end;

  TTscData = class(TObject)
    private
      FRec  : TTsrRec;
    published
      property Rec  : TTsrRec read FRec write FRec;
  end;

TTscDataクラスのRecプロパティに値を書き込みたい場合、どうなるでしょうか。

procedure TForm3.FormCreate(Sender: TObject);
var
  data  : TTscData;
begin
  data  := TTscData.Create;
  data.Rec.Name := 'Test';
  data.Rec.No   := 1;
end;

実はこれ、コンパイルできません。
E2064エラーがでます。代入できないんですね。
上のような実装をした場合、これに値を書き込みたい場合はこうなります。

procedure TForm3.FormCreate(Sender: TObject);
var
  data  : TTscData;
  rec   : TTsrRec;
begin
  rec.Name  := 'Test';
  rec.No    := 1;
  data  := TTscData.Create;
  data.Rec  := rec;
end;

実装内容や仕様によっては、この使い方でも問題ないでしょうが
できればレコードのメンバに直接書き込みたいなと思うことも多いでしょう。
ではどうすればいいのか。

レコードを拡張すればいいんです。
Delphiのレコード型はクラス方のような実装ができます。


レコードにプロパティを用意する

レコードの実装を少々変更しました。

type
  TTsrRec = record
    private
      FName : string;
      FNo   : Integer;
      procedure SetName(name:string);
      procedure SetNo(no:integer);
    public
      property Name : string read FName write SetName;
      property No   : Integer read FNo write SetNo;
  end;
implementation

procedure TTsrRec.SetName(name:string);
begin
  FName := name;
end;

procedure TTsrRec.SetNo(no:Integer);
begin
  FNo := no;
end;

プロパティメソッドを実装し、レコードのメンバに書き込みをする場合はそれぞれSetName、SetNoプロシージャが呼び出されます。
このような実装をすると、レコードのメンバに直接値を書き込めるようになります。

見てのとおり、レコード型はクラスのような実装ができ、なんならイベントの実装とかも普通にできます。じゃぁ、クラスと何が違うんやというと。

  • レコードからの継承はできない
  • レコードは可変部分を持てる
  • レコードは値型、クラスは参照型
  • レコードはコンストラクタを使って自動生成されるが、クラスは明示的に生成する
  • レコードのコンストラクタはデフォルトの引数なしがあるため、ユーザー定義のコンストラクタには引数が1つ以上必要
  • レコードはデストラクタを持てない
  • 継承に対応しないので、当然virtualやdynamicなんかもサポートしない。
  • レコードはWin32プラットフォームでインターフェースを実装できない

と、こんなところです。
特に継承できるのか否かは大きいと思います。
なので、どちらで実装するかはケースバイケースでって感じで。

ビット反転アルゴリズム

数年前にFFTライブラリのためにビット反転処理を書いた。
ただ、FFTサンプル数を増やしたときに崩壊してしまっていたので、サンプル数に制限をかけてたわけですが
一思いにこの辺の処理を一新することにした。

続きを読む

SecureBridgeを使って、SSHログインとシェルを動かした。。。けど謎。

Delphi向けの有料コンポーネントのSecureBridgeを使って、SSHログインとシェルコマンドを実行させる手順をまとめときます。

開発元が公開しているマニュアルがあまりにも読みづらかったので、試行錯誤しながらなんとか動いた感じなので間違いは多々ある気もする。
あと、非常に謎が多い。よくわかってないとこがあるんですよね。嫌な感じ。

続きを読む

Raspberry PiのバックアップをCLIから作成する

Raspberry Piのバックアップを作成する手段として
1.Win32DiskImagerを使う
2.SD Card Copierを使う
といったところがよく使われるみたいですが、

Win32DiskImagerはSDカードの未使用領域まですべてをイメージ化するので、
元のSDカードより容量の低いものには書けません。
それどころか、同容量でもメーカーや個体差により総容量には微妙な差があり書けないこともあります。

SD Card Copierは、実際に使用している領域のみ書き込むので、元のSDより小さいものでも書けます。
(さすがに使用している容量以上のものは必要)
ただ、GUIでしか使えないのでCLIで動作させているRaspberry Piでは切り替えないと使えません。

ということで、CLIからSD Card Copierと同等の性能をもったrpi-cloneを使ってバックアップを作成していきます。

続きを読む