2012年10月2日火曜日

FizzBuzzHelper


Delphi XE3 で導入されたプリミティブ型への record helper を弄ってみます。

※この記事を書いてから、そういえば Team Japan で高橋さんが書いていたのを思い出しました!
高橋さんの記事のほうが詳しいです!必見!

ヘルパは、継承を使用せずにクラスを拡張する方法であり、継承がまったく許可されないレコードにとっても便利なものです。ヘルパは、識別子を解決するときに、コンパイラが使用するスコープの範囲を広げる機能です。(引用元:Delphi ヘルプ)

上記の引用の通り、record helper / class helper は、構造体 / Class を「後から」拡張する仕組みです。
後から変更しづらいクラスや構造体を拡張できます。
特に構造体は、継承出来ないので record helper は有用な方法といえます。

そして!
record helper は record という名前が付いていますが、XE3 からプリミティブ型に適用できるようになりました。

例えば↓こんな風に定義できます。

TStringHelper = record helper for String
end;

TBooleanHelper = record helper for Boolean
end;

この機構を採り入れた事により、Delphi 言語もモダンな書き方ができるようになりました。

例えば↓こんな風にです。

// 文字列の長さを表示
// (Team Japan ブログにある TIntegerHelper.ToString を実装してあるとして)
ShowMessage('文字列'.Length.ToString); 
Delphi 言語では String 型はプリミティブ型です。クラスで実装されているわけではないので、このような書き方はできませんでした。

今回は、record helper を利用して、Integer 型自身に、自分が Fizz なのか Buzz なのかを判定させてみます。

FizzBuzz とは、3で割り切れる数字の時 Fizz を、5で割り切れる数字の時 Buzz を、3と5で割り切れる時 Fizz Buzz と出力する非常に簡単なプログラムのことです。

コードは↓こんな感じです。
program FizzBuzzHelper;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TFizzBuzzHelper = record helper for Integer
    function ToFizzBuzz: String;
  end;

function TFizzBuzzHelper.ToFizzBuzz: String;
begin
  Result := '';

  if (Self mod 3 = 0) then
    Result := 'Fizz ';

  if (Self mod 5 = 0) then
    Result := Result + 'Buzz';

  if (Result = '') then
    Result := IntToStr(Self);
end;

var
  i: Integer;
begin
  for i := 1 to 100 do
    Writeln(i.ToFizzBuzz);
end.

ここで注目すべきは Self です。
プリミティブ型の Self は、それ自身の値を示します。
StringHelper なら、Self は String 型の値、IntegerHelper なら Self は Integer 型の値になります。

record helper を使えば、色々面白いことができそうです。

0 件のコメント:

コメントを投稿